如何为容器中的Junit测试创建模拟/虚拟初始上下文

时间:2011-04-12 15:28:27

标签: hibernate spring weblogic junit4

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

我的问题是当JUnit测试时,我需要让weblogic服务器在本地机器上运行,只是为了初始化JMS代理中使用的WeblogicInitialContext。我的junit测试不需要向服务器,NO JMS,NO数据源发送任何内容。所有这些都是由弹簧单元测试框架进行的。 我想为我的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。

请帮忙。

Exception的某些部分;

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: 

2 个答案:

答案 0 :(得分:2)

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

将应用程序配置拆分为两部分,

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

添加一个弹簧配置,将它们全部导入,并在启动应用程序时使用它。

因此,对于测试,您可以使用核心部分配置。如果无法实现此配置,因为缺少某些bean(构成服务器相关部分),您需要模拟它们。这里有两个选择:

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

无论如何:我强烈建议您重新考虑构建测试的方式。可能更好的方法是在没有spring的情况下完全构建一些(并非所有)测试并手动创建测试类({{ 1}})并手动“注入”测试所需的对象。测试不需要的对象(或者因为使测试更难但不是更好)应该用模拟代替。


为了创造嘲笑,我更喜欢嘲弄的框架jMock。我已经使用Factory方法实现了一个Helper类,它创建了一个类,并为@ Autorwird / @Ressourse注释的所有字段创建和注入Mocks。

答案 1 :(得分:0)

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

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