【问题标题】:How to create mock/ dummy Initial context for Junit tests out of container如何为容器外的 Junit 测试创建模拟/虚拟初始上下文
【发布时间】:2011-08-04 00:13:15
【问题描述】:

在运行 jUnit 测试时,我在实例化 weblogic 初始上下文时遇到了大问题。 应用程序使用 Spring/hibernate/weblogic。 在应用程序代码中,方法使用 JMS 代理向 JMS 发送消息,队列在 weblogic 上设置。

我的问题是,目前 JUnit 测试时,我需要让 weblogic 服务器在本地机器上运行,只是为了初始化在 JMS 代理中使用的 WeblogicInitialContext。我的 junit 测试不需要向服务器发送任何东西,没有 JMS ,没有数据源。所有都由弹簧单元测试框架处理。 我想为我的 junit 测试解耦/摆脱 Weblogic。请建议。 这是我的代码:

这是我的测试应用程序上下文 XML:

<beans xmlns="http://www.springframework.org/schema/beans"
...
>

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<util:properties id="webLogicInitialContext">
    <prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
    <prop key="java.naming.provider.url">t3://localhost:7001</prop>
    <prop key="java.naming.security.principal">admin</prop>
    <prop key="java.naming.security.credentials">password</prop>
</util:properties>

<jee:jndi-lookup id="responseProxyConnectionFactory"
    jndi-name="jms/ConnectionFactory" environment-ref="webLogicInitialContext"/>

<bean id="responseProxyJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory"
        ref="responseProxyConnectionFactory" />
</bean>
</beans>

这是一种 Java 类方法:

public class Order {
    public void addOrder(OrderRequest addOrderRequest) {
        PurchaseOrder newOrder = orderHelper.createOrder(addOrderRequest);
        orderDaoHibernate.addOrder(newOrder);
        responseProxy.send(newOrder);

    }
}

我的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners( {TransactionalTestExecutionListener.class, DependencyInjectionTestExecutionListener.class,DirtiesContextTestExecutionListener.class })
@ContextConfiguration(locations={"/test-application-context.xml"})
@TransactionConfiguration(defaultRollback=true) 

public class TestOrder {

    @Test
    @Transactional
    public void testMyOrder(){
        Order ord = new Order();
        OrderRequest req = new OrderRequest();
        ....
        ord.addOrder(req);
    }

}

如果我运行这个测试,Spring 框架会尝试加载 WeblogicInitialContext ,如果本地 weblogic 没有运行它会抛出异常。

当我从 Junit 调用此方法时,我不想发送任何 JMS 消息。 如何创建虚拟 WeblogicInitialContext。

请帮忙。

异常的一部分;

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean     with name 'responseProxyConnectionFactory': Invocation of init method failed; nested exception is javax.naming.CommunicationException [Root exception is java.net.ConnectException: t3://localhost:7001: Destination unreachable; nested exception is: 

【问题讨论】:

标签: hibernate spring weblogic junit4


【解决方案1】:

如果这是您与生产应用程序共享的通用上下文,我会说可以通过将 JMS 相关 bean 移动到仅由您的主应用程序加载的不同上下文中来避免实例化数据库和 JMS 内容,并且不是测试代码。

但由于这是一个专用的测试上下文,您可能可以简单地删除那些不需要的 bean,例如 weblogic 配置和 jndi 上下文查找 bean。如果你仍然需要一个 jms 队列来再次测试,你可以使用一个 mock,如this SO question 中所述。

【讨论】:

  • 我试过了。如果我删除这些 weblogic 配置 bean,它会开始抛出其他无法找到 InitialContext 的异常等。实际上,我的应用程序中的所有方法都通过代理发送 JMS,而在我的配置 xml 中,reponseProxy 使用 weblogicContext。在我的代码中,我可以进行更改/放置一个在单元测试调用时不发送 JMS 的开关,但问题是 SPRING 在开始编码之前加载所有配置 XML。我不想避免任何 Initial context 的负载,或者使用一些模拟 InitialContext。
【解决方案2】:

解决这个问题的一种方法是:

将您的应用程序配置分成两部分,

  • 核心部分 - 定义、注入、扫描普通类...
  • 与服务器相关的部分(包含在测试中无法创建的所有内容)

添加一个 spring 配置,将它们都导入,并在您启动应用程序时使用它。

因此,您可以使用 core-part-configuration 进行测试。如果无法实例化此配置,因为缺少某些 bean(形成服务器相关部分),您需要模拟它们。在这里你有两个选择:

  • 创建一个测试模拟配置,通过模拟模拟服务器相关部分。
  • 您可以在加载核心部分之前尝试以编程方式将模拟添加到应用程序上下文中。 (更复杂)

无论如何:我强烈建议重新考虑构建测试的方式。可能更好的方法是完全不使用 spring 构建一些(不是全部)测试并手动创建被测类 (@987654323 @) 并手动“注入”测试所需的对象。测试不需要的对象(根本,或者因为使测试更难而不是更好)应该由 Mocks 替换。


要创建模拟,我更喜欢模拟框架jMock。我已经实现了一个带有 Factory 方法的 Helper Class,它创建一个类,并为 @Autorwird/@Ressourse 注释的所有字段创建和注入 Mocks。

【讨论】:

  • Tks。这就是问题所在,我如何创建模拟服务器端部分。如何在我的 spring 配置文件中模拟 WeblogicInitialContext?我只是不想加载这个上下文。但是我的代码中的代理正在使用它。控制永远不会进入代码级别,但我的测试在初始化 spring 配置文件本身时失败。
  • @utsuk:我已经扩展了我的回答。这是你要求的吗?
  • Tks 拉尔夫。我目前没有使用任何模拟框架,但看看你提到的这个 jMock。实际上,我正在寻找的是一种在我的 spring 配置文件中通过某种方式模仿 WLInitialContextFactory 的方法。就像用其他类型的上下文工厂替换它一样,这样我就不需要在本地启动 weblogic。我只是希望我的测试在加载弹簧配置文件时不会失败,因为它找不到 WLInitialContextFactory。例如。用一些虚拟工厂替换它,比如 "dummyContectFactory 或 "SpringInitialContextFactory" 。
  • ..continued.. 然后我的 responseProxy 代码将得到这个模拟工厂和配置加载正常。例如:dummy.jndi.DummyContextFactory@ 987654322@> admin密码
  • 我希望,您只注入工厂的结果,而不是工厂本身。所以我认为你不需要“模拟”工厂。只需删除工厂,然后将工厂的结果添加到您的测试上下文中。
猜你喜欢
  • 2012-07-31
  • 2021-09-22
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 1970-01-01
相关资源
最近更新 更多