Arquillian 单元测试

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

我公司的许多 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 中。