Testing with Aliens; How to test a JPA type converter with Arquillian

JPA type converters provide an easy way to define how an entity attribute gets persisted to the database. You can use them to implement lots of different features, e.g. to encrypt your data as I showed in a previous post: How to use a JPA Type Converter to encrypt your data
But writing the type converter is not enough. We also need to make sure, that it is working correctly.

In general, there are two ways to test a type converter. We could write a unit test to check, if the conversion works correctly. But a unit test performs a test of the isolated class without putting it into the real execution environment. That means that we will still not know, if the converter works in one of our applications. If everything is set up correctly, the persistence provider will call the converter before writing to and after reading from the database. So we also need to check if the type converter gets called by the persistence provider and if everything works fine under that condition. We need to test the converter inside of the container we want to use for our application.

We will have a look at how this can be done with Arquillian and its persistence extension.

Something about Arqillian

If you are already familiar with Arquillian, you can skip this part. For all of you who have never worked with Arquillian so far, I just want to give some basic information. You can find a more detailed description at the Arquillian Getting Started guide.

Arquillian is a test framework for in container testing. The idea is to do not mock the container you want to use but to test your code inside of it. This provides the advantage, that you can test if your code will also work in your execution environment and not only in your mocked up test scenario. Arquillian provides lots of functionality to manage the container, inject required resources like EJBs or an EntityManager and make your live much easier.

The Arquillian tests are executed by junit. This is great, because you can use them everywhere, where you can execute junit tests. And that means in your IDE, as part of your build process, on your CI server, simply everywhere.

Object under test

The following code snippet shows the object under test for this example. It is a type converter that encrypts and decrypts a String attribute. The converter gets called by the persistence provider before writing to and after reading from the database. If you want to read more about how this type converter works, check my posting about it.

@Converter
public class CryptoConverter implements AttributeConverter<String, String> {

    private static final String ALGORITHM = "AES/ECB/PKCS5Padding";
    private static final byte[] KEY = "MySuperSecretKey".getBytes();

    @Override
    public String convertToDatabaseColumn(String ccNumber) {
      // do some encryption
      Key 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);
      }
    }

    @Override
    public String convertToEntityAttribute(String dbData) {
      // do some decryption
      Key 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);
      }
    }
}

Setting it up

Before we can start to write our tests, we need to define a few dependencies. I will only show how to configure the dependencies we need for this example. If you have not already set up arquillian tests for your project, you will have to do a little bit more. Please check the Getting Started guide to learn how to setup arquillian for your project. Don’t be afraid, there is not too much to do.

As you can see in the following snippet, we will use JUnit 4.11, Arquillian 1.1.3.Final, the Arquillian Persistence Extension 1.0.0.Alpha7 and the WildFly Application Server 8.1.0.Final.

<?xml version="1.0" encoding="UTF-8"?>
<project
    xsi: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>

Writing the tests

There are two things we need to do to setup our test environment. At first, we need to tell junit that this test shall be executed as a junit test. This is done by @RunWith(Arquillian.class).

Additionally, we need to create the test deployment, that will be deployed to the container. Therefore we need to implement at least one method and annotate it with @Deployment. As you can see in the following code snippet, we use ShrinkWrap to create a jar archive deployment. The archive contains the CreditCard entity, the CryptoConverter type converter and the test class. There is no need to include any EJBs or other classes which implement business logic. We can inject the EntityManager into our test case and use it directly to persist and read entities. We will have a more detailed look at it later on.

Additionally, we need to add some manifest resources to create a persistence unit, register the type converter and add an empty beans.xml to activate CDI. Please check the getting started guide to get more information on ShrinkWrap and creating deployments.

@RunWith(Arquillian.class)
public class TestCryptoConverter {

    @Deployment
    public 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");
    }

After this is done, we can start to write the test cases. At first, we will persist a CreditCard entity and check, if the credit card number gets encrypted by the CryptoConverter. Therefore we inject the EntityManager, create a CreditCard entity and pass it to the persist method of the EntityManager. The validation of the persisted data, is done by the Arquillian persistence extension. We just need to define the data we expect to be written to the database. The expected data is defined in the cc.yml file, which is referenced in the @ShouldMatchDataSet annotation. Because the id attribute is generated by the database, we want to exclude it from the validation. This can be done by referencing it in the excludeColumns attribute of the annotation.

    @PersistenceContext
    private 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);
    }

The cc.yml contains the following information.

CreditCard:
  - id: 1
    name: My Name
    ccNumber: egFfkhd8cRh82tvsh3VVUg==

In the second test, we will check if we can search the database for a CreditCard entity with a given credit card number. Therefore we use the @UsingDataSet annotation to seed the database with data defined in the cc.yml file. Now we can use the injected EntityManager to call a named query to search for CreditCard entity with the given number.

    @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());
    }

Conclusion

We used Arquillian and the Arquillian Persistence extension to test a JPA type converter. Therefore we injected the EntityManager and used the annotations @ShouldMatchData and @UsingDataSet to validate and seed the database with a yml file.
If you want to try it yourself, you can find the sources on github.
You can run it by calling: git clone https://github.com/thjanssen/JPA2.1.git && cd JPA2.1/CryptoConverter && mvn test

What are your experiences with testing your Java EE application with Arquillian? Please write a comment about it.

Want to learn more about Arquillian, see the Arquillian Guides: http://arquillian.org/guides/

About the author

Thorben Janssen is a senior developer with more than 10 years of experience in Java EE development and architecture. During these years he acted as developer, architect, project and technical lead to create high available, clustered mobile billing solutions and laboratory information management systems.
Visit his blog: http://www.thoughts-on-java.org or follow him on twitter and google+ to read more about Java EE7 and Arquillian.

Arquillian Persistence Extension 1.0.0.Alpha7 Released

The Arquillian team is proud to announce the 1.0.0.Alpha7 release of the Arquillian Persistence Extension component!

After quite a while we are happy to announce new version of Arquillian Persistence Extension with anticipated fixes and improvements.

Big thanks go to Sándor Bodó-Merle, Michel Graciano, Masao Kunii, kumm and Jakub Narloch for their contributions as well as all users who gave us feedback on the community forums.

Some of the highlights in this release

SQL script handling improvements

SQL script handling has been significantly improved. It not only has improved performance (namely for Oracle) but also let you provide your own implementation for parsing multi-line scripts through simple SPI org.jboss.arquillian.persistence.spi.script.StatementSplitter.

Direct access to DBUnit

Ability to inject DBUnit DatabaseConnection making it possible to interact with DBUnit directly in the tests.

@ArquillianResource
private DatabaseConnection databaseConnection;
New SPI module

Through newly introduce SPI module you can now register your own datasource providers. This can be leveraged by frameworks such as Spring which can now do their own lookups (from application context) instead of relying on JNDI.

New extension point

We have also implemented extension point to define custom implementation of org.dbunit.database.DatabaseSequenceFilter which is used to seed and clean database by DBUnit. Out of the box we provide sequence filter strategy for Oracle. You can register it in arquillian.xml as part of persistence-dbunit

<property name=“filterTables”>true</property>
<property name=“customTableFilter”>org.jboss.arquillian.persistence.dbunit.filter.OracleDatabaseSequenceFilterProvider</property>
Custom filtering strategy

You can also define column filtering strategy when comparing datasets through @ShouldMatchDataSet annotation. By simply providing an implementation of org.dbunit.dataset.filter.IColumnFilter and decorating your test with e.g. @CustomColumnFilter({FirstNameColumnFilter.class, LastNameColumnFilter.class}). Filter classes are packaged automatically.

This version comes with latest DBUnit 2.5.0.

We’ve also extended our test suite by adding Apache Tomee to our continuous integration pipeline.

We are still shaping up the extension and its modularity hence we split modules in the following manner:
persistence-api
persistence-core
persistence-dbunit – you can replace old impl dependency by this one
persistence-spi – SPI for future extensions

We look forward to hearing your feedback about this release in the community forums!

What is Arquillian?

Arquillian is open source software that empowers you to test JVM-based applications more effectively. Created to defend the software galaxy from bugs, Arquillian brings your test to the runtime so you can focus on testing your application's behavior rather than managing the runtime. Using Arquillian, you can develop a comprehensive suite of tests from the convenience of your IDE and run them in any IDE, build tool or continuous integration environment.

Release details

Component Arquillian Persistence Extension
Version 1.0.0.Alpha7 view tag
Release date 2014-05-12
Released by Aslak Knutsen
Compiled against

Published artifacts org.jboss.arquillian.extension

  • org.jboss.arquillian.extension » arquillian-persistence-api jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-core jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-dbunit jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-spi jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-integration-tests jar javadoc pom

Release notes and resolved issues 0

Thanks to the following list of contributors: Bartosz Majsak, Aslak Knutsen, Kumm, Sandor Bodo-merle, Michel Graciano, Masao Kunii, Jakub Narloch

Arquillian Persistence Extension 1.0.0.Alpha6 Released

The Arquillian team is proud to announce the 1.0.0.Alpha6 release of the Arquillian Persistence Extension component!

Arquillian Persistence Extension is back on the release train and the future plan is stronger than ever. The Alpha6 release brings a lot of improvements and fixes thanks to invaluable feedback from the community.

Big thanks go to Marco Cella, Matti Linnanvuori, Bernard Łabno, Tiago Wanke Marques, Karsten Ohme, Vineet Reynolds, Cyrill Ruettimann, Bryan Saunders, Anton Shaykin, Nicolas-Xavier Vanderlinden and Noah White for their feedback which led us to fix some minor annoyances and shortcomings of APE. We are proud of the vibrant and active community around Arquillian!

Some of the highlights in this release

Transaction support has been replaced with Transaction Extension. By default the JTA implementation is included. The only thing you will need to change in your tests is the import sttement for the @Transactional annotation. From now on it’s under org.jboss.arquillian.transaction.api.annotation.

Support for row ordering when comparing datasets. When using Generated ID’s for instance, such as UUID’s, the rows need to be sorted in order for the DbUnit comparison to pass. If they are not ordered, then the assertion is unreliable.

Improved error reporting, including rows comparision and misconfigured entries.

DTD support for flat XML data sets (DBUnit feature).

Proper support for multiple line SQL scripts with comments (ANSI SQL compliant)

We’ve also extended our test suite by adding Apache Derby to our continuous integration pipeline.

Important change: We re-groupped configuration entries arquillian.xml giving them more qualifiers:
persistence – for all basic settings
persistence-dbunit – for DBUnit specific configuration
persistence-script – for SQL related things
Please refer to our confluence documentation for detailed description.

We look forward to hearing your feedback about this release in the community forums!

What is Arquillian?

Arquillian is open source software that empowers you to test JVM-based applications more effectively. Created to defend the software galaxy from bugs, Arquillian brings your test to the runtime so you can focus on testing your application's behavior rather than managing the runtime. Using Arquillian, you can develop a comprehensive suite of tests from the convenience of your IDE and run them in any IDE, build tool or continuous integration environment.

Release details

Component Arquillian Persistence Extension
Version 1.0.0.Alpha6 view tag
Release date 2013-03-07
Released by Aslak Knutsen
Compiled against

Published artifacts org.jboss.arquillian.extension

  • org.jboss.arquillian.extension » arquillian-persistence-api jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-impl jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-integration-tests jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-integration-tests-testng jar javadoc pom

Release notes and resolved issues 0

Thanks to the following list of contributors: Bartosz Majsak, Jakub Narloch, Aslak Knutsen, Vineet Reynolds, Artur Dryomov

Arquillian Persistence Extension 1.0.0.Alpha5 Released

The Arquillian team is proud to announce the 1.0.0.Alpha5 release of the Arquillian Persistence Extension component!

We are back with a bunch of handy new additions and some bug fixes, so keep on reading..

Big kudos goes to Tomas Hradec for his great contribution on the “JPA Cache Eviction” support. You can now control your second level cache directly from the Arquillian tests. I would also like to thank Adrian Gonzalez, Alex Holmansky, Anton Shaykin and Christoph Rohr for their feedback which led us to fix some minor annoyances and shortcomings of APE. We are proud of the vibrant and active community around Arquillian!

Some of the highlights in this release

Instead of relying on the JPA provider you can now use your custom scripts to create the schema and populate data for each test. The only thing you have to do is decorate your test class with the following annotation:

@CreateSchema({"create-schema.sql", "populate-data.sql"})

Thanks to Tomas Hradec we have taken control over the Second Level JPA cache eviction. This initial implementation gives you a possibility to evict the cache before or after your test. Just specify which persistence unit(s) should be used by APE:

@JpaCacheEviction(entityManager = { "java:comp/env/MyPersistenceUnit" })

One of the shortcomings of the previous versions was the fact that you were always forced to provide the data source name explicitly. Either through arquillian.xml or by using the @DataSource annotation. With Alpha 5 you won’t have to. If you only use one data source in the test case, it will be inferred automatically from the persistence.xml used by your test.

You can also tell DBUnit which schema needs to be used for seeding the database. Just add the schema property to your arquillian.xml configuration as illustrated in the snippet below:

arquillian.xml
<extension qualifier="persistence-dbunit">
    <property name="schema">ape</property>
</extension>

We’ve also extended our test suite by adding the following databases to our continuous integration pipeline

  • MySQL 5.5.24
  • PostgreSQL 9.1.4

Important change: We renamed two properties used in arquillian.xml giving them more appropriate names:
initStatement became scriptsToExecuteBeforeTest
cleanupStatement became scriptsToExecuteAfterTest
Moreover you can now specify list of scripts (or files) seperated by comma.

We look forward to hearing your feedback about this release in the community forums!

What is Arquillian?

Arquillian is open source software that empowers you to test JVM-based applications more effectively. Created to defend the software galaxy from bugs, Arquillian brings your test to the runtime so you can focus on testing your application's behavior rather than managing the runtime. Using Arquillian, you can develop a comprehensive suite of tests from the convenience of your IDE and run them in any IDE, build tool or continuous integration environment.

Release details

Component Arquillian Persistence Extension
Version 1.0.0.Alpha5 view tag
Release date 2012-08-31
Released by Aslak Knutsen
Compiled against

Published artifacts org.jboss.arquillian.extension

  • org.jboss.arquillian.extension » arquillian-persistence-api jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-impl jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-integration-tests jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-integration-tests-testng jar javadoc pom

Release notes and resolved issues 0

Thanks to the following list of contributors: Bartosz Majsak, Aslak Knutsen, Tomas Hradec

Arquillian Persistence Extension 1.0.0.Alpha4 Released

The Arquillian team is proud to announce the 1.0.0.Alpha4 release of the Arquillian Persistence Extension component!

It’s been a while since the Alpha3 release. After three long months, we’re excited to announce Alpha 4 with a lot of improvements and enhancements suggested by our great community. Best of all, we finally have complete documentation in the reference guide!

I would especially like to thank Michael Brill for nailing down DBUnit clean up strategies, Pål Oliver Kristiansen and Jarek Gilewski for suggesting customization of DBUnit behaviour and Juergen Zimmermann for spotting a bug with transactional support. Last, but not least, many thanks to all who actively discussed the roadmap for next releases. There is plenty of great stuff on the way! Thank you very much for your feedback!

Some of the highlights in this release

Custom SQL scripts for cleanup
You can now use custom SQL scripts to clean your database before or after the test. For this purpose use the @CleanupUsingScript annotation and specify SQL files which have to be executed.
More flexible custom SQL scripts execution
We’ve removed the @UsingScript annotation and replaced it with the @ApplyScriptBefore and @ApplyScriptAfter annotations.
DBUnit insert strategies

You can tell DBUnit how it should insert your data. The following strategies are available:

  • INSERT – Performs insert of the data defined in provided data sets. This is the default strategy.
  • CLEAN_INSERT – Performs insert of the data defined in provided data sets, after removal of all data present in the tables referred in provided files.
  • REFRESH – During this operation, existing rows are updated and new ones are inserted. Entries already existing in the database which are not defined in the provided data set are not affected.
  • UPDATE – This strategy updates existing rows using data provided in the datasets. If the dataset contains a row which is not present in the database (identified by its primary key) then an exception is thrown.
DBUnit cleanup modes

You can specify when and how you would like your database to be cleaned. By default, your database is erased entirely before each test. If you want to control this behavior, use the @Cleanup annotation for this purpose. The following modes are currently supported:

  • STRICT – Cleans the entire database. This strategy might require turning off database constraints (e.g. referential integrity).
  • USED_ROWS_ONLY – Deletes only those entries that are defined in the datasets used for seeding.
  • USED_TABLES_ONLY – Deletes only those tables that are referenced in datasets.

You can also specify when you would like to invoke the cleanup procedure. For instance:

@Cleanup(phase = TestExecutionPhase.AFTER, strategy = CleanupStrategy.USED_ROWS_ONLY)

You can invoke cleanup BEFORE or AFTER the test. You can also disable cleanup by using TestExecutionPhase.NONE.

Column filtering for data set matching
@ShouldMatchDatSet has been enhanced with columnsToExclude list, where you can specify which columns shouldn’t be used for database content verification.
Nullable columns
For XML, JSON and YAML you can now set arbitary columns to null using [null] placeholder.
Separated configuration for core and (enhanced) DBUnit specific features

We provide configuration for all DBUnit properties and features as of Alpha 4! Moreover there is a split for core properties (such as default data source or JNDI of UserTransaction) and DBUnit related settings, as the example below illustrates:

arquillian.xml
<extension qualifier="persistence">
    <property name="defaultDataSource">java:app/datasources/mssql_ds</property>
    <property name="userTransactionJndi">java:jboss/UserTransaction</property>
    <property name="initStatement">scripts/mssql-identity-insert-on.sql</property>
    <property name="cleanupStatement">scripts/mssql-identity-insert-off.sql</property>
</extension>
          
          <extension qualifier=“persistence-dbunit”>
<property name=“datatypeFactory”>org.dbunit.ext.mssql.MsSqlDataTypeFactory</property>
<property name=“useIdentityInsert”>true</property>
</extension>

For complete list, please refer to the reference guide.

We look forward to hearing your feedback about this release in the community forums!

What is Arquillian?

Arquillian is open source software that empowers you to test JVM-based applications more effectively. Created to defend the software galaxy from bugs, Arquillian brings your test to the runtime so you can focus on testing your application's behavior rather than managing the runtime. Using Arquillian, you can develop a comprehensive suite of tests from the convenience of your IDE and run them in any IDE, build tool or continuous integration environment.

Release details

Component Arquillian Persistence Extension
Version 1.0.0.Alpha4 view tag
Release date 2012-04-12
Released by Aslak Knutsen
Compiled against

Published artifacts org.jboss.arquillian.extension

  • org.jboss.arquillian.extension » arquillian-persistence-api jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-impl jar javadoc pom
  • org.jboss.arquillian.extension » arquillian-persistence-integration-tests jar javadoc pom

Release notes and resolved issues 0

Thanks to the following list of contributors: Bartosz Majsak, Aslak Knutsen