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

发布于 2024-10-31 23:48:04 字数 2821 浏览 5 评论 0原文

我在运行 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

转身泪倾城 2024-11-07 23:48:04

处理这个问题的一种方法是:

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

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

添加一个 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,

  • a core part - where your normal classes are defined, injected, scanned, ...
  • a server dependent part (containing all the stuff which can not been created in the test)

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:

  • create a test mock configuration, that simulated the server dependent part by mocks.
  • you could try to add the mocks programaticaly to the application context, before you load the core part. (much more compicated)

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.

空气里的味道 2024-11-07 23:48:04

如果这是您与生产应用程序共享的公共上下文,我想说可以通过将 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文