如何在容器外为 Junit 测试创建模拟/虚拟初始上下文
我在运行 jUnit 测试时面临实例化 weblogic 初始上下文的大问题。 应用程序使用Spring/hibernate/weblogic。 在应用程序代码中,方法使用JMS代理将消息发送到JMS,队列在weblogic上设置。
我的问题是,当前 JUnit 测试时我需要保持 Weblogic 服务器在本地计算机上运行,只是为了初始化 JMS 代理中使用的 WeblogicInitialContext。我的 junit 测试不需要向服务器发送任何内容,没有 JMS ,没有数据源。所有这些都由 spring 单元测试框架处理。 我想为我的 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:
I am facing big problem instantiating weblogic Initial context while running jUnit tests.
Application uses Spring / hibernate / weblogic.
In application code, methods uses JMS proxy to send messages to JMS, Queues are setup on weblogic.
My problem is while JUnit tests currently I need to keep weblogic server running on local machine just to initialize WeblogicInitialContext which is used in JMS proxies. My junit test don't need to send anything to server, NO JMS , NO datasources. All are handeled by spring unit test framework.
I want to decouple/ get rid of Weblogic for my junit tests. Please suggest.
Here is my code:
This is my test application context 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>
This is One Java class methods :
public class Order {
public void addOrder(OrderRequest addOrderRequest) {
PurchaseOrder newOrder = orderHelper.createOrder(addOrderRequest);
orderDaoHibernate.addOrder(newOrder);
responseProxy.send(newOrder);
}
}
My Test :
@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);
}
}
If I run this test the Spring framework try to load the WeblogicInitialContext , and if local weblogic not running it throws exceptions.
I don't want to send any JMS message when I call this method from Junit.
How can I create dummy WeblogicInitialContext.
Please help.
Some part of 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:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
处理这个问题的一种方法是:
将应用程序配置分成两部分,
添加一个 spring 配置,将它们都导入,并在启动应用程序时使用它。
因此,为了进行测试,您可以使用 core-part-configuration。如果此配置无法实例化,因为缺少一些bean(形成服务器依赖部分),您需要模拟它们。这里你有两个选择:
无论如何:我强烈建议重新考虑构建测试的方式。可能更好的方法是完全不使用 spring 构建一些(不是全部)测试并手动创建被测类(
new
) 并手动“注入”测试所需的对象。测试不需要的对象(根本不需要,或者因为它们只会使测试变得更困难而不是更好)应该用 Mock 替换。要创建模拟,我更喜欢模拟框架 jMock。我已经使用工厂方法实现了一个辅助类,它创建一个类,并为 @Autorwird/@Ressourse 注释的所有字段创建和注入模拟。
One way to deal with this problem is this:
Split your application configuration in two parts,
Add a spring config, that import them both, and use this when you start your application.
So for test you can use the core-part-configuration. If this configuration can not be instanciated, because some beans (form the server dependent part) are missing you need to mock them. Here you have two choices:
Anyway: I strongly recommend to rethink the way you build tests. May a better way is to build some (not all) tests completely without spring and create the class under test by hand (
new
) and "inject" the objects needed for the test by hand. The objects not needed for the test (at all, or because the make the test only more difficult but not better) should be replaced by Mocks.To create mocked, I prefere the mocking framwork jMock. I have implemented a Helper Class with a Factory method, which create a class, and create and inject Mocks for all fields annoted by @Autorwird/@Ressourse.
如果这是您与生产应用程序共享的公共上下文,我想说可以通过将 JMS 相关 bean 移动到仅由主应用程序而不是测试代码加载的不同上下文来避免实例化数据库和 JMS 内容。
但由于这是一个专用的测试上下文,您可能可以简单地删除那些不需要的 bean,例如 weblogic 配置和 jndi 上下文查找 bean。如果您仍然需要 jms 队列来再次测试,您可以使用模拟,如 这个问题。
If this were a common context that you're sharing with your production application, I would say that can avoid instantiating the database and JMS stuff by moving the JMS related beans into a different context that is loaded only by your main application and not test code.
But since this is a dedicated test context, you can probably simply remove those beans that are not needed, such as the weblogic config and the jndi context lookup bean. If you still need a jms queue to test again, you can use a mock, as described in this SO question.