Java EE 6测试第二部分– Arquillian和ShrinkWrap简介

在Java EE 6测试的第一部分中,我简要介绍了使用Glassfish嵌入式容器的EJB 3.1 Embeddable API,以演示如何启动该容器,如何在项目类路径中查找bean以及运行非常简单的集成测试。

这篇文章重点介绍Arquillian和ShrinkWrap以及为什么它们是用于企业Java应用程序集成测试的出色工具。

可以在GitHub上的arquillian-shrinkwrap文件夹下找到用于本文的源代码。

工具

Arquillian
Arquillian将测试执行带到目标运行时,从而减轻了开发人员从测试或项目构建中管理运行时的负担。 要反转此控件,Arquillian将生命周期包装在执行以下操作的测试执行周围:
  • 管理一个或多个容器的生命周期
  • 将测试用例,相关类和资源捆绑为ShrinkWrap档案
  • 将档案部署到容器
  • 通过依赖注入和其他声明式服务丰富测试用例
  • 在容器内部(或针对容器)执行测试
  • 将结果返回给测试跑步者进行报告

收缩包装

ShrinkWrap是Arquillian的核心组件,它提供了一种简单的机制,可以使用友好,流利的API来组装JAR,WAR和EAR等档案。

使用Arquillian的主要好处之一是,您可以在远程容器(即应用程序服务器)中运行测试。 这意味着您将测试真实的交易 。 没有嘲笑。 甚至没有嵌入式运行时!

议程

这篇文章将涵盖以下主题:

  • 在基于Maven的Java项目中配置Arquillian基础架构
  • 直接在测试实例中注入EJB和受管Bean(CDI)
  • 测试Java持久性API(JPA)层
  • 在客户端模式下运行Arquillian
  • 在IDE中运行和调试Arquillian测试

配置Maven以运行集成测试

要使用Maven运行集成测试,我们需要一种不同的方法。 通过不同的方法,我指的是一个不同的插件: Maven故障安全插件 。

故障安全插件是Maven Surefire插件的分支,旨在运行集成测试。

Failsafe插件目标旨在在集成测试阶段的程序包阶段之后运行。

Maven生命周期有四个运行集成测试的阶段:

  • 集成前测试:在此阶段,我们可以启动任何必需的服务或执行任何操作,例如启动数据库或启动Web服务器,等等。
  • 集成测试:故障安全将在此阶段运行测试,因此在所有必需的服务启动之后。
  • 集成后测试:关闭所有服务的时间…
  • 验证: failsafe运行另一个在此处解释测试结果的目标,如果没有通过任何测试,failsafe将显示结果并退出构建。

在POM中配置故障保护:

<!-- clip -->
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.12</version><configuration><skipTests>true</skipTests></configuration>
</plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-failsafe-plugin</artifactId><version>2.12</version><configuration><encoding>UTF-8</encoding></configuration><executions><execution><id>integration-test</id><goals><goal>integration-test</goal></goals></execution><execution><id>verify</id><goals><goal>verify</goal></goals></execution></executions>
</plugin>
<!-- clip -->

默认情况下,Surefire插件执行**/Test*.java**/*Test.java**/*TestCase.java测试类。 Failsafe插件将查找**/IT*.java**/*IT.java**/*ITCase.java 。 如果同时使用Surefire和Failsafe插件,请确保使用此命名约定,以使其更容易识别哪个插件正在执行哪些测试。

在Maven中配置Arquillian基础架构

通过附加以下XML片段,将Maven项目描述符配置为使用Arquillian:

<!-- clip -->
<repositories><repository><id>jboss-public-repository-group</id><name>JBoss Public Repository Group</name><url>http://repository.jboss.org/nexus/content/groups/public/</url></repository>
</repositories><dependencyManagement><dependencies><dependency><groupId>org.jboss.arquillian</groupId><artifactId>arquillian-bom</artifactId><version>1.0.1.Final</version><scope>import</scope><type>pom</type></dependency></dependencies>
</dependencyManagement><dependencies><dependency><groupId>org.jboss.arquillian.testng</groupId><artifactId>arquillian-testng-container</artifactId><scope>test</scope></dependency><dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>6.4</version><scope>test</scope></dependency><dependency><groupId>org.jboss.spec</groupId><artifactId>jboss-javaee-6.0</artifactId><version>3.0.1.Final</version><scope>provided</scope><type>pom</type></dependency>
</dependencies><profiles><profile><id>jbossas-remote-7</id><activation><activeByDefault>true</activeByDefault></activation><dependencies><dependency><groupId>org.jboss.as</groupId><artifactId>jboss-as-arquillian-container-remote</artifactId><version>7.1.1.Final</version><scope>test</scope></dependency></dependencies></profile>
</profiles>
<!-- clip -->

Arquillian有大量的容器适配器 。 Arquillian测试可以在与测试中使用的编程模型兼容的任何容器中执行。 但是,在本文中,仅使用JBoss AS 7。
与Java EE 6测试第I部分类似,我选择使用TestNG测试框架,但同样, JUnit应该也能正常工作。

创建可测试的组件

在研究如何使用Arquillian编写集成测试之前,我们首先需要有一个要测试的组件。
会话Bean是Java EE堆栈中的常见组件,将用作测试主题。 在本文中,我将创建一个非常基本的后端,用于向数据库中添加新用户。

@Stateless
public class UserServiceBean {@PersistenceContextprivate EntityManager em;public User addUser(User user) {em.persist(user);return user;}// Annotation says that we do not need to open a transaction@TransactionAttribute(TransactionAttributeType.SUPPORTS)public User findUserById(Long id) {return em.find(User.class, id);}
}

在上面的代码中,我使用JPA ,因此我们需要一个持久性单元。
持久性单元定义由应用程序中的EntityManager实例管理的所有实体类的集合。 这组实体类表示单个数据存储中包含的数据。 持久性单元由persistence.xml配置文件定义:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"version="2.0"><persistence-unit name="example"><jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source><properties><property name="hibernate.hbm2ddl.auto" value="create-drop" /><property name="hibernate.show_sql" value="true" /></properties></persistence-unit>
</persistence>

在本示例中,我使用的示例数据源使用H2数据库,并且已经使用JBoss AS 7进行了配置。

最后,我们还需要一个映射到数据库表的实体:

@Entity
public class User {@Id@GeneratedValueprivate Long id;@NotNullprivate String name;// Removed constructors, getters and setters for brevity@Overridepublic String toString() {return "User [id=" + id + ", name=" + name + "]";}
}

使用Arquillian测试JPA

现在,我们都准备编写我们的第一个Arquillian测试。
Arquillian测试用例看上去就像带有一些额外功能的单元测试。 它必须具有三件事:

  • 扩展Arquillian类(这特定于TestNG,对于JUnit,您需要在类上使用@RunWith(Arquillian.class)批注)
  • 用@Deployment注释的公共静态方法,该方法返回ShrinkWrap存档
  • 至少一种用@Test注释的方法
public class UserServiceBeanIT extends Arquillian {private static final Logger LOGGER = Logger.getLogger(UserServiceBeanIT.class.getName());@Injectprivate UserServiceBean service;@Deploymentpublic static JavaArchive createTestableDeployment() {final JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "example.jar").addClasses(User.class, UserServiceBean.class).addAsManifestResource("META-INF/persistence.xml", "persistence.xml")// Enable CDI.addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));LOGGER.info(jar.toString(Formatters.VERBOSE));return jar;}@Testpublic void callServiceToAddNewUserToDB() {final User user = new User("Ike");service.addUser(user);assertNotNull(user.getId(), "User id should not be null!");}
}

该测试非常简单,它插入一个新用户并检查id属性是否已被数据库生成的值填充。
由于Arquillian丰富了该测试,因此通常可以使用@EJB@Inject批注来注入EJB和受管bean。
@Deployment注释的方法使用ShrinkWrap来构建一个JAR归档文件,该归档文件将部署到容器中并对其进行测试。 ShrinkWrap将测试所需的类和资源与类路径的其余部分隔离开来,您应该包括测试所需的每个组件才能在部署存档中运行。

客户端模式

Arquillian支持三种测试运行模式:

  • 容器内模式用于测试您的应用程序内部。 这使Arquillian能够与测试进行通信,丰富测试并远程运行测试。 在这种模式下,测试在远程容器中执行; Arquillian默认使用此模式。
  • 客户端模式用于测试客户端如何使用您的应用程序。 与容器内模式重新打包并覆盖测试执行相反,客户端模式的作用尽可能小。 它不会重新打包@Deployment也不会将测试执行转发到远程服务器。 您的测试用例正在JVM中按预期运行,并且您可以自由地从外部测试容器,如客户所见。 Arquillian唯一要做的就是控制@Deployment的生命周期。
  • 混合模式允许在同一测试类中混合两种运行模式。

要以客户端模式运行Arquillian,首先要构建要测试的servlet:

@WebServlet("/User")
public class UserServlet extends HttpServlet {private static final long serialVersionUID = -7125652220750352874L;@Injectprivate UserServiceBean service;@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/plain");PrintWriter out = response.getWriter();out.println(service.addUser(new User("Ike")).toString());out.close();}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {doGet(request, response);}
}

现在让我们测试一下:

public class UserServletIT extends Arquillian {private static final Logger LOGGER = Logger.getLogger(UserServletIT.class.getName());// Not managed, should be used for external calls (e.g. HTTP)@Deployment(testable = false)public static WebArchive createNotTestableDeployment() {final WebArchive war = ShrinkWrap.create(WebArchive.class, "example.war").addClasses(User.class, UserServiceBean.class, UserServlet.class).addAsResource("META-INF/persistence.xml")// Enable CDI.addAsWebInfResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));LOGGER.info(war.toString(Formatters.VERBOSE));return war;}@RunAsClient // Same as @Deployment(testable = false), should only be used in mixed mode@Test(dataProvider = Arquillian.ARQUILLIAN_DATA_PROVIDER)public void callServletToAddNewUserToDB(@ArquillianResource URL baseURL) throws IOException {// Servlet is listening at <context_path>/Userfinal URL url = new URL(baseURL, "User");final User user = new User(1L, "Ike");StringBuilder builder = new StringBuilder();BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));String line;while ((line = reader.readLine()) != null) {builder.append(line);}reader.close();assertEquals(builder.toString(), user.toString());}
}

尽管此测试非常简单,但它允许您通过单个方法调用来测试应用程序的多个层。

在Eclipse中运行测试

您可以从IDE内部运行Arquillian测试,就像单元测试一样。

运行Arquillian测试

(点击图片以放大)

  • 安装TestNG和JBoss Tools Eclipse插件。
  • 将新的JBoss AS服务器添加到Eclipse:
  • 启动JBoss AS服务器:
  • 从Eclipse运行测试用例,右键单击Project Explorer上的测试文件,然后选择

Run As > TestNG Test

结果应类似于以下内容:

调试Arquillian测试

(点击图片以放大)

由于我们使用的是远程容器,因此Debug As > TestNG Test不会导致断点被激活。
相反,我们需要以调试模式启动容器并附加调试器。 这是因为测试是在与原始测试运行器不同的JVM中运行的。 调试测试所需要做的唯一更改是在调试模式下启动JBoss AS服务器:

  • 启动JBoss AS服务器调试模式:
  • 将所需的断点添加到代码中。
  • 并通过右键单击Project Explorer上的测试文件并选择它来调试它

Run As > TestNG Test

    更多资源

    我希望能够强调Arquillian的一些好处。
    有关Arquillian的更多信息,请查看以下资源:

    • Arquillian指南
    • Arquillian社区
    • Arquillian Git存储库

    相关文章

    • 单元测试JBoss 5服务
    • Java EE 6测试第I部分– EJB 3.1可嵌入API
    • Maven 2 Cobertura插件–更新
    • JBoss PojoCache配置
    • JBoss AS 5.0已经发布!
    • 上一篇文章:Java EE 6测试第I部分– EJB 3.1可嵌入API
    • 下一篇文章:比较OpenDDR与WURFL

    参考: Java EE 6测试第II部分–来自我们JCG合作伙伴 Samuel Santos的Arquillian和ShrinkWrap简介,位于Samaxes博客上。


    翻译自: https://www.javacodegeeks.com/2012/06/java-ee-6-testing-part-ii-introduction.html

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372561.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    linux内存分配堆栈数据段代码段,linux – LD_PRELOAD堆栈和数据段内存分配

    你好,我正在编写一个Linux模块(基于名为“Ccontrol”的GitHub项目)来创建缓存分区(a.k.a页面着色),以减轻定时侧通道攻击(用于防止Prime Probe等攻击).我已经使用LD_PRELOAD系统env变量来覆盖所有malloc(),calloc()和free()调用,并用颜色感知调用替换它们.现在我正在寻找颜色堆…

    【腾讯Bugly干货分享】Android内存优化总结实践

    本文来自于腾讯Bugly公众号&#xff08;weixinBugly&#xff09;&#xff0c;未经作者同意&#xff0c;请勿转载&#xff0c;原文地址&#xff1a;https://mp.weixin.qq.com/s/2MsEAR9pQfMr1Sfs7cPdWQ 导语 智能手机发展到今天已经有十几个年头&#xff0c;手机的软硬件都已经发…

    以编程方式向OpenJPA注册实体类型

    我刚刚开始为Isis开发 OpenJPA对象库 。 在一般情况下&#xff0c;可以在persistence.xml文件中注册实体类型。 但是&#xff0c;Isis是一个框架&#xff0c;可以构建自己的元模型&#xff0c;并且可以自行确定哪些类构成实体。 因此&#xff0c;我不想强​​迫开发人员重复自己…

    linux redis客户端,Redisson 3.4.0和2.9.0发布,Redis客户端

    Redisson 3.4.0和2.9.0发布&#xff0c;Redis客户端发布时间:2017-04-27 09:12:16来源:红联作者:baihuoRedisson于2017年4月26日发布了3.4.0和2.9.0版本Redisson是架设在Redis基础上的一个Java驻内存数据网格(In-Memory Data Grid)。充分的利用了Redis键值数据库提供的一系列优…

    LeetCode 349 Intersection of Two Arrays

    Given two arrays, write a function to compute their intersection. Example: Given nums1 [1, 2, 2, 1], nums2 [2, 2], return [2]. 思路&#xff1a; 利用ArrayList的contains(Object o)方法进行交集的查询。 解法&#xff1a; 1 import java.util.ArrayList;2 3 publi…

    shell脚本1——变量 $、read、``

    与Shell变量相关的几个命令&#xff1a; 变量只在当前Shell中生效. source 这个命令让脚本影响他们父Shell的环境&#xff08;. 可以代替source命令&#xff09; export 这个命令可以让脚本影响其子Shell的环境 () unset 从环境中删除变量 其他几个与变量有关的命令&#xff1…

    令人印象深刻的第一个Apache Camel版本

    为了准备下周的CamelOne会议&#xff0c;我花了一些时间回顾一下Apache Camel项目的历史。 因此&#xff0c;除其他外&#xff0c;我了解了Apache Camel的第一个正式1.0版本 。 Apache Camel 1.0 – 5年前 我看的越多&#xff0c;这个版本的事实给我留下了深刻的印象。 现在您…

    Linux禁用user01账户,Linux 管理用户 useradd

    创建用户、设置密码、修改用户、删除用户&#xff1a;useradd testuser 创建用户testuseruseradd [选项]useradd 命令选项-u uid:指定新用户的uid,默认用当前最大uid加1-g group:指定新用户所在的组(私有组),该组必须存在-G group:指定新用户的附加组-d dir:指定新用户的自家目…

    css小细节

    1. 文字居中显示 水平居中&#xff1a; text-align: center; 垂直居中&#xff1a; line-height: (height); 2.子元素相对于父元素的绝对布局。 父元素一定要 position: relative/absolute/fixed; 默认position 是static 转载于:https://www.cnblogs.com/zcancandice/p/5…

    为什么在2012/2013年我将在新的Enterprise Java项目中继续使用Spring *和* Java EE

    自从我担任技术决策职务以来已经过去了一年多&#xff0c;很高兴看到我仍然与之保持着完美的和谐。 几个月前&#xff0c;我在KaiWhner的一个不错的博客中写了一个有关JEE与Spring的答案。 如果观点没有不同&#xff0c;那么讨论的附加值在哪里&#xff1f; 我确实同意Kai的许多…

    linux ubuntu 五笔输入法,ubuntu下安装fcitx五笔输入法

    安装fcitx输入法sudo add-apt-repository ppa:fcitx-team/stable #添加安装源&#xff0c;apt-get 添加&#xff0c;nightly源也可以sudo apt-get update #更新源&#xff0c;否则无法安装fcit…

    浅谈Windows下SVN在Android Studio中的配置、基本使用及解除关联

    看到网上很多关于svn环境配置和关联Android-Studio的很多博文&#xff0c;发现很零散&#xff0c;想集大家所长整理一下&#xff1a; 在AndroidStudio中开发版本控制中&#xff0c;除了Git就是SVN&#xff0c;和Eclipse不同Android Studio没有提供单独的插件&#xff0c;只能和…

    四. 基于环视Camera的BEV感知算法-BEVDepth

    目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习下课程第四章——基于环视Cam…

    【腾讯Bugly干货分享】Android Patch 方案与持续交付

    本文来自于腾讯bugly开发者社区&#xff0c;非经作者同意&#xff0c;请勿转载&#xff0c;原文地址&#xff1a;http://dev.qq.com/topic/57a31921ac3a1fb613dd40f3 Android 不仅系统版本众多&#xff0c;机型众多&#xff0c;而且各个市场都各有各的政策和审核速度&#xff0…

    App Engine中的Google Services身份验证,第1部分

    这篇文章将说明如何构建一个简单的Google App Engine&#xff08;GAE&#xff09;Java应用程序&#xff0c;该应用程序可针对Google进行身份验证&#xff0c;并利用Google的OAuth授权访问Google的API服务&#xff08;例如Google Docs&#xff09;。 此外&#xff0c;在Google已…

    c语言中空格的作用是什么,C语言中空格和\0的区别

    \0 为字符串结束符&#xff0c;比如说&#xff1a;abcd (空格)cdefg&#xff1b;存入数组时&#xff0c;空格作为一个字符占有一个字节的空间&#xff0c;我们可以把它看着一个字符去处理。而“\0 ” 则是这个字符串的结束标识符&#xff0c;也占有一个字节的空间&#xff0c;表…

    C++11 新特性:Lambda 表达式

    参考文章&#xff1a;https://blogs.oracle.com/pcarlini/entry/c_1x_tidbits_lambda_expressions 或许&#xff0c;Lambda 表达式算得上是 C 11 新增特性中最激动人心的一个。这个全新的特性听起来很深奥&#xff0c;但却是很多其他语言早已提供&#xff08;比如 C#&#xff0…

    山东自考c语言程序设计停考了吗,2018山东自考停考专业有哪些

    自考每年都会停考一批的专业以适应社会的发展&#xff0c;今年山东自考的停考专业有哪些&#xff1f;本文由学梯网小编整理发布&#xff0c;仅供参考。2018年山东自考停考专业有什么根据山东省教育考试院发布的《关于山东自学考试停考国际贸易(专科)等19个专业的通知》知悉&…

    公开调用私有Java方法?

    我们是Java开发人员&#xff0c;在Java中已知4种访问修饰符&#xff1a;私有&#xff0c;受保护&#xff0c;公共和包。 好吧&#xff0c;除了私有外&#xff0c;最后三个可以通过继承&#xff0c;相同的包或实例从类外部调用。 现在&#xff0c;常见的问题是&#xff0c;可以公…

    Java 异常处理 try catch finally throws throw 的使用和解读(一)

    最近的一个内部表决系统开发过程中&#xff0c;发现对异常处理还存在一些模棱两可的地方&#xff0c;所以想着整理一下主要涉及到&#xff1a;1.try catch finally throws throw 的使用和解读2.自定义异常的使用3.常见的运行异常 /** * Java 异常处理 * try catch finally thr…