我公司的许多 JEE 和 Spring 项目都迫切需要可靠的测试用例。但是由于多种原因,人们反对测试套件。其中最有趣的是我们的开发人员对单元测试表现出普遍的冷漠,他们不想编写测试代码,因为他们不会为他们的简历增加价值。经理们也不鼓励团队将时间浪费在好的回归测试套件上。每个人都失去了测试套件的价值。
我希望 JBoss Arquillian 可以改变这些观点。在 IDE 中执行的简单干净的容器测试帮助我们测试 JEE/Spring 方面。如果开发人员学习 Arquillian 的代码和设计,测试套件还可以使他们了解 Spring 和 JEE 的复杂性。
当我开始使用 Arquillian 时,我发现 JBoss Arquillian 论坛收到的问题和回答更少。这没有帮助,但 Arquillian 展示 有很多例子。
Arquillian WildFly 测试套件 有更多示例,但更难理解。
我展示了一些我在本文中学到的基本测试规则。
容器
我安装了 WildFly 并将 JBOSS_HOME 变量设置为指向安装并激活 pom.xml 中指定的 Maven 配置文件 arq-jbossas-managed 。就这些。 Maven POM 负责处理 Arquillian 所需的容器依赖项。支持许多容器适配器。
部署
学习使用 ShrinkWrap API 编写代码以创建 Web 部署存档是最重要的部分。我见过团队每天部署代码数百次来测试简单的功能。有时他们需要连接到客户的虚拟环境以进行部署和测试。
Arquillian 自动并重复地为我们将所有内容部署到容器中。
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
添加测试和其他类
可以向已部署的 WAR 添加类包或单个类
加载依赖
加载项目依赖的方式有很多种。
使用 API 显式加载单个依赖项
此代码根据项目的 artifactid 、 groupid 和 版本 解析我们需要的项目依赖项
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
检查内容
我遇到的大多数问题都是由于我不了解 ShrinkWrap 如何打包工件造成的。遵循简化的调试过程会缩短学习周期。
这是转储打包 WAR 内容的一种方法
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
我很好奇我的 测试 类的位置,因为它们在此列表中不可见,我认为它应该在 /WEB-INF/lib/0165719c-f843-4f44-94e1-58a6cb544351.jar 中。 Arquillian 允许我们将整个 WAR 转储到 arquillian.xml 中指定的位置,以便进一步检查它。事实上,在这个例子中,这是 arquillian.xml 的唯一目的,尽管它也可以用于其他目的。
arquillian.xml
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
在我的例子中导出的 WAR 是 _DEFAULT___DEFAULT__ShrinkWrap.war 并且我验证了 WEB-INF/lib/0165719c-f843-4f44-94e1-58a6cb544351.jar 包含我添加的类。
也可以像这样使用 API 打印内容。
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
使用 ShrinkWrap 导入现有的 WAR
通常我们已经有了一个要在其上执行测试的 Web 或企业存档。以下代码使用现有的 WAR 。
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
应用上下文.xml
这与任何其他此类文件一样。
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
JMS 设置
我使用了创建嵌入式 Broker 的示例设置。
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
ActiveMQ Broker 的调试日志
用于验证代理是否正确启动和停止的日志。
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
pom.xml
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
JMS 单元测试示例
这部分是在 Arquillian showcase 中找到的示例测试。由 IDE 执行,显示成功为绿色条。
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
@Deployment
public static WebArchive createWebArchive() {
final WebArchive war=ShrinkWrap.create(WebArchive.class,"ShrinkWrap.war");
JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
//.addPackage("com.arquillian.jms.e2e");
.addClass("com.arquillian.jms.e2e.MessageSender")
.addClass("com.arquillian.jms.e2e.MessageSenderImpl")
.addClass("com.arquillian.jms.e2e.ShrinkWrappedMessageTest");
war.addAsLibrary(jar);
war.addAsResource("applicationContext-another.xml");
war.addAsResource("applicationContext.xml");
war.addAsResource("spring-beans-embedded.xml");
war.addAsResource("arquillian.xml");
war.addAsResource("log4j.xml");
loadDependencies( war );
l.info(war.toString(Formatters.VERBOSE));
return war;
}
来源在 Arquillian Source 中。