我想使用arquillian测试我的glassfish应用程序中包含的JMS-worker(以获得容器服务)。我的工作人员看起来如下:
package queue.worker;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.MessageListener;
@MessageDriven(mappedName = "java:app/jms/MailQueue", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") })
public class MailWorker implements MessageListener {
public MailWorker() {
}
@Override
public void onMessage(javax.jms.Message inMessage) {
}
}
这是测试:
package queueTest.worker;
import java.io.File;
import javax.inject.Inject;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import queue.worker.MailWorker;
@RunWith(Arquillian.class)
public class MailWorkerTest {
@Deployment
public static WebArchive createDeployment() {
WebArchive archive = ShrinkWrap
.create(WebArchive.class)
.addClasses(MailWorker.class)
.addAsWebInfResource(new File("src/test/resources/WEB-INF/glassfish-resources.xml"),
"glassfish-resources.xml")
.addAsWebInfResource(new File("src/main/webapp/WEB-INF/beans.xml"), "beans.xml");
return archive;
}
@Inject
protected MailWorker mailWorker;
@Test
public void sendRegisterMail() {
Assert.assertTrue(true);
}
}
执行此测试,Glassfish-JSM-Queue已启动[1],但我收到以下错误:
org.jboss.weld.exceptions.DeploymentException:WELD-001408在注入点[[field] @Inject protected queueTest.worker.MailWorkerTest.mailWorker]
当我在Mailworker.class中删除“@MessageDrivern [...]”并将其替换为“@ApplicationScoped”时,例如,一切正常 - 所以Arquillian似乎没有问题,但是JMS-相关。
如何测试JMS / Queue-Worker?
[1] Dez 23,2012 12:42:08 AM com.sun.messaging.jms.ra.ResourceAdapter start 信息:MQJMSRA_RA1101:GlassFish MQ JMS资源适配器启动:代理是EMBEDDED,连接模式是直接 Dez 23,2012 12:42:10 AM com.sun.messaging.jms.ra.ResourceAdapter start 信息:MQJMSRA_RA1101:GlassFish MQ JMS资源适配器已启动:EMBEDDED
答案 0 :(得分:3)
测试MDB比测试通常的EJB和CDI bean更难,因为它们是异步执行的。即使你能够将它们注入到测试中,你也可以通过同步调用它来测试onMessage()方法。
我的方法使用MDB来捕获消息并提取底层表示(如String或Object)。然后将提取的消息传递给一个单独的CDI bean,它有一个测试备选方案。
@MessageDriven(mappedName = "jms/queue/example", activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination",
propertyValue = "jms/queue/example")
})
public class ExampleMDB implements MessageListener {
@Inject
private ExampleMessageHandler exampleMessageHandler;
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
exampleMessageHandler.doSomething(textMessage.getText());
} catch (JMSException e) {
throw new RuntimeException("That was unexpected!", e);
}
}
}
}
ExampleMessageHandler定义了doSomething(String text)。
对于测试范围,我们需要一个实现来捕获传递给doSomething()的参数,并使它们可以被测试类访问。您可以通过以下实现来实现此目的:
@Alternative
@ApplicationScoped
public class ExampleMessageHandlerTestable implements ExampleMessageHandler {
private BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
public void doSomething(String text) {
queue.add(text);
}
public String poll(int secondsUntilInterrupt) throws InterruptedException {
return queue.poll(secondsUntilInterrupt, TimeUnit.SECONDS);
}
}
这是生产代码使用的实际实现的CDI替代方案。现在让Arquillian测试使用这个替代方案。这是测试类:
@RunWith(Arquillian.class)
public class ExampleMDBGoodTest {
@Resource(mappedName = "ConnectionFactory", name = "ConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(mappedName = "jms/queue/example", name = "jms/queue/example")
private Queue queue;
@Inject
private ExampleMessageHandler exampleMessageHandler;
@Deployment
public static WebArchive createDeployment() {
WebArchive archive = ShrinkWrap.create(WebArchive.class, "exampleMDB.war")
.addPackages(true, ExampleMDB.class.getPackage())
.addAsWebInfResource("hornetq-jms.xml", "hornetq-jms.xml")
.addAsWebInfResource("beans-alternative.xml", "beans.xml");
System.out.println(archive.toString(true));
return archive;
}
@Test
public void testOnMessage() throws Exception {
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
TextMessage textMessage = session.createTextMessage("Hello world!");
producer.send(textMessage);
session.close();
connection.close();
// We cast to our configured handler defined in beans.xml
ExampleMessageHandlerTestable testHandler =
(ExampleMessageHandlerTestable) exampleMessageHandler;
assertThat(testHandler.poll(10), is("Hello world!"));
}
}
一些解释在这里发生了什么:测试请求JMS ConnectionFactory和MDB侦听的队列。这些创建了受测试的MDB使用的JMS消息。然后我们创建一个测试部署。 hornetq-jms.xml为测试定义了一个特殊队列。通过包含beans-alternative.xml,我们确保MDB使用我们的测试替代方案。
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<alternatives>
<class>com.github.mcs.arquillian.mdb.example.ExampleMessageHandlerTestable</class>
</alternatives>
</beans>
测试用例本身应该是直截了当的。将新的JMS消息发送到队列。然后我们等待最多10秒钟,在我们的测试选项中添加新消息。通过使用阻塞队列,我们可以定义超时,在此之后测试失败。但是一旦MDB调用替代bean,测试本身就立即完成。
我已从我复制上述代码部分的位置上传了一个小Maven example project。因为我对Glassfish了解不多,所以它使用JBoss作为托管容器。根据您可能使用的JBoss版本,您需要更改jboss-as-arquillian-container-managed的版本。
希望能帮到某人: - )
答案 1 :(得分:1)
MDB不符合注入其他类的资格。你不能将它们注入你的测试用例。