如何在JUnit中构建自动回复JMS侦听器(在OpenEJB中)

Den*_*nys 4 java junit jms message-driven-bean openejb

我有一个EJB向JMS队列发送消息并等待它的回复.我想测试EJB,很容易使用OpenEJB来进行EJB的JUnit测试.但问题是这个EJB会等待JMS响应继续进行.

虽然我可以在我的junit代码中发送消息,但由于EJB仍在进行中,所以在EJB完成之前我无法运行它.

第二个解决方案是我可以初始化一个MDB来监听和回复来自EJB的JMS消息,但问题是MDB必须在src\main\java中而不能在src\test\java中.问题是这只是一个测试代码,我不应该将它打包到生产环境中.(我用Maven)

或者我应该使用模拟对象?

Dav*_*ins 6

你走在正确的轨道上.有几种方法可以解决这个问题.以下是使用OpenEJB和Maven进行单元测试的几个技巧.

测试豆子

您可以编写各种EJB和其他测试实用程序并部署它们.所有你需要的是一个ejb-jar.xml测试代码,如下所示:

  • src/main/resources/ejb-jar.xml (正常的)

  • src/test/resources/ejb-jar.xml (测试豆)

像往常一样,ejb-jar.xml文件只需要包含<ejb-jar/>,仅此而已.它的存在只是告诉OpenEJB检查类路径的那一部分并扫描它的bean.扫描整个类路径非常慢,所以这只是提高速度的惯例.

TestCase注射

通过上述内容,src/test/resources/ejb-jar.xml您可以非常轻松地添加仅测试MDB,并将其设置为以TestCase所需的方式处理请求.但它src/test/resources/ejb-jar.xml也开辟了一些其他有趣的功能.

您可以TestCase通过声明对所需JMS资源的引用并将它们注入来实现自己.

import org.apache.openejb.api.LocalClient;

@LocalClient
public class ChatBeanTest extends TestCase {

    @Resource
    private ConnectionFactory connectionFactory;

    @Resource(name = "QuestionBean")
    private Queue questionQueue;

    @Resource(name = "AnswerQueue")
    private Queue answerQueue;

    @EJB
    private MyBean myBean;


    @Override
    protected void setUp() throws Exception {
        Properties p = new Properties();
        p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
        InitialContext initialContext = new InitialContext(p);

        initialContext.bind("inject", this); // here's the magic!
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您只需要一个线程就可以响应测试用程序本身的JMS消息.你可以启动一个可以读取单个消息的runnable,发送你想要的响应,然后退出.

也许是这样的:

public void test() throws Exception {

    final Thread thread = new Thread() {
        @Override
        public void run() {
            try {
                final Connection connection = connectionFactory.createConnection();

                connection.start();

                final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

                final MessageConsumer incoming = session.createConsumer(requestQueue);
                final String text = ((TextMessage) incoming.receive(1000)).getText();

                final MessageProducer outgoing = session.createProducer(responseQueue);
                outgoing.send(session.createTextMessage("Hello World!"));

            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    };
    thread.setDaemon(true);
    thread.start();

    myBean.doThatThing();

    // asserts here...
}
Run Code Online (Sandbox Code Playgroud)

看到

替代描述符

如果您确实想要使用MDB解决方案并且只希望仅针对一个测试而不是所有测试src/test/resources/mockmdb.ejb-jar.xml启用它,则可以在特殊文件中对其进行定义,并在需要它的特定测试用例中启用它.

有关如何启用该描述符以及备用描述符的各种选项的更多信息,请参阅此文档.