jpa 测试
该帖子与+ Aslak Knutsen ( @aslakknutsen )一起撰写。
JPA类型转换器为定义实体属性如何持久存储到数据库提供了一种简便的方法。 您可以使用它们来实现许多不同的功能,例如,如上一篇文章中所示:加密数据: 如何使用JPA Type Converter加密数据 。
但是编写类型转换器是不够的。 我们还需要确保其正常运行。
通常,有两种方法可以测试类型转换器。 我们可以编写一个单元测试来检查转换是否正常工作。 但是,单元测试可以对隔离的类进行测试,而无需将其放入实际的执行环境中。 这意味着我们仍然不知道转换器是否可以在我们的应用程序之一中工作。 如果一切设置正确,则持久性提供程序将在写入数据库和从数据库读取之前调用转换器。 因此,我们还需要检查持久性提供程序是否调用了类型转换器,以及在这种情况下一切是否正常。 我们需要在要用于我们的应用程序的容器内测试转换器。
我们将看看如何使用Arquillian及其持久性扩展来完成此任务。
关于Arqillian
如果您已经熟悉Arquillian,则可以跳过此部分。 对于到目前为止从未与Arquillian合作的所有人,我只想提供一些基本信息。 您可以在《 Arquillian 入门指南》中找到更详细的描述。
Arquillian是用于容器测试的测试框架。 这个想法是不要模拟您要使用的容器,而是在其中测试您的代码。 这样做的好处是,您可以测试代码是否还可以在执行环境中工作,而不仅是在模拟的测试场景中。 Arquillian提供了许多功能来管理容器,注入所需的资源(例如EJB或EntityManager),并使您的工作变得更加轻松。
Arquillian测试由junit执行。 这很棒,因为您可以在可以执行junit测试的任何地方使用它们。 这意味着在您的IDE中,作为构建过程的一部分,您可以在CI服务器上的任何地方。
被测对象
下面的代码片段显示了此示例中的测试对象。 这是一个类型转换器,用于加密和解密String属性。 在写入数据库和从数据库读取之后,持久性提供程序将调用该转换器。 如果您想了解有关此类型转换器如何工作的更多信息,请查看有关它的文章 。
@Converter
public class CryptoConverter implements AttributeConverter<String, String> {private static final String ALGORITHM = "AES/ECB/PKCS5Padding";private static final byte[] KEY = "MySuperSecretKey".getBytes();@Overridepublic String convertToDatabaseColumn(String ccNumber) {// do some encryptionKey key = new SecretKeySpec(KEY, "AES");try {Cipher c = Cipher.getInstance(ALGORITHM);c.init(Cipher.ENCRYPT_MODE, key);return Base64.encodeBytes(c.doFinal(ccNumber.getBytes()));} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic String convertToEntityAttribute(String dbData) {// do some decryptionKey key = new SecretKeySpec(KEY, "AES");try {Cipher c = Cipher.getInstance(ALGORITHM);c.init(Cipher.DECRYPT_MODE, key);return new String(c.doFinal(Base64.decode(dbData)));} catch (Exception e) {throw new RuntimeException(e);}}
}
设定
在开始编写测试之前,我们需要定义一些依赖关系。 我将仅展示如何配置此示例所需的依赖项。 如果您尚未为项目设置Arquillian测试,则必须做更多的工作。 请查看入门指南,以了解如何为您的项目设置Arquillian。 不要害怕,没有太多的事情要做。
如下面的代码片段所示,我们将使用JUnit 4.11 , Arquillian 1.1.3.Final , Arquillian Persistence Extension 1.0.0.Alpha7和WildFly Application Server 8.1.0.Final 。
<?xml version="1.0" encoding="UTF-8"?>
<projectxsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">...<properties><version.junit>4.11</version.junit><version.arquillian>1.1.3.Final</version.arquillian><version.arquillian_persistence>1.0.0.Alpha7</version.arquillian_persistence><version.wildfly>8.1.0.Final</version.wildfly></properties><dependencyManagement><dependencies>...<dependency><groupId>org.jboss.arquillian</groupId><artifactId>arquillian-bom</artifactId><version>${version.arquillian}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies>...<dependency><groupId>javax.enterprise</groupId><artifactId>cdi-api</artifactId><scope>provided</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${version.junit}</version><scope>test</scope></dependency><dependency><groupId>org.jboss.arquillian.junit</groupId><artifactId>arquillian-junit-container</artifactId><scope>test</scope></dependency><dependency><groupId>org.jboss.arquillian.extension</groupId><artifactId>arquillian-persistence-dbunit</artifactId><version>${version.arquillian_persistence}</version><scope>test</scope></dependency></dependencies>
编写测试
要设置测试环境,我们需要做两件事。 首先,我们需要告诉junit该测试应作为junit测试执行。 这是通过@RunWith(Arquillian.class)
。
另外,我们需要创建测试部署,该部署将部署到容器中。 因此,我们需要实现至少一种方法,并使用@Deployment
对其进行@Deployment
。 如下面的代码片段所示,我们使用ShrinkWrap创建jar存档部署。 存档包含CreditCard
实体, CryptoConverter
类型转换器和测试类。 无需包括任何实现业务逻辑的EJB或其他类。 我们可以将EntityManager注入我们的测试用例中,并直接使用它来持久化和读取实体。 稍后我们将对其进行更详细的介绍。
另外,我们需要添加一些清单资源来创建一个持久性单元,注册类型转换器并添加一个空的beans.xml来激活CDI。 请查看入门指南,以获取有关ShrinkWrap和创建部署的更多信息。
@RunWith(Arquillian.class)
public class TestCryptoConverter {@Deploymentpublic static JavaArchive createDeployment() {return ShrinkWrap.create(JavaArchive.class).addClasses(CreditCard.class, CryptoConverter.class,TestCryptoConverter.class).addAsManifestResource("META-INF/persistence.xml","persistence.xml").addAsManifestResource("META-INF/orm.xml", "orm.xml").addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");}
完成之后,我们可以开始编写测试用例了。 首先,我们将保留一个CreditCard
实体,并检查信用卡号是否已通过CryptoConverter
加密。 因此,我们注入了EntityManager,创建了CreditCard
实体,并将其传递给EntityManager的persist方法。 持久化数据的验证由Arquillian持久性扩展完成。 我们只需要定义我们希望写入数据库的数据即可。 预期数据在cc.yml文件中定义,该文件在@ShouldMatchDataSet
批注中引用。 由于id属性是由数据库生成的,因此我们希望将其从验证中排除。 这可以通过在注释的excludeColumns属性中引用它来完成。
@PersistenceContextprivate EntityManager em;@Test@ShouldMatchDataSet(value = "data/cc.yml", excludeColumns = "id")public void testEncryption() {CreditCard cc = new CreditCard();cc.setName("My Name");cc.setCcNumber("123456789");this.em.persist(cc);}
cc.yml包含以下信息。
CreditCard:- id: 1name: My NameccNumber: egFfkhd8cRh82tvsh3VVUg==
在第二个测试中,我们将检查是否可以在数据库中搜索具有给定信用卡号的CreditCard
实体。 因此,我们使用@UsingDataSet
批注为cc.yml文件中定义的数据播种数据库。 现在,我们可以使用注入的EntityManager来调用命名查询,以使用给定的编号搜索CreditCard
实体。
@Test@UsingDataSet("data/cc.yml")public void testRead() {CreditCard cc = this.em.createNamedQuery(CreditCard.BY_NUMBER, CreditCard.class).setParameter("number", "123456789").getSingleResult();Assert.assertEquals("My Name", cc.getName());}
结论
我们使用Arquillian和Arquillian Persistence扩展来测试JPA类型转换器。 因此,我们注入了EntityManager并使用批注@ShouldMatchData
和@UsingDataSet
来验证数据库并@UsingDataSet
添加yml文件。
如果您想自己尝试,可以在github上找到源代码。
您可以通过调用以下命令来运行它:git clone https://github.com/thjanssen/JPA2.1.git && cd JPA2.1 / CryptoConverter && mvn测试。
使用Arquillian测试Java EE应用程序有什么经验? 请对此发表评论。
想要了解有关Arquillian的更多信息,请参阅Arquillian Guides: http ://arquillian.org/guides/
翻译自: https://www.javacodegeeks.com/2014/06/testing-with-aliens-how-to-test-a-jpa-type-converter-with-arquillian.html
jpa 测试