Today I will describe my newly discovered library which is an extension to the great JBoss Arquillian project.

The mission of the Arquillian project is to provide a simple test harness that abstracts away all container lifecycle and deployment from the test logic so developers can easily produce a broad range of integration tests for their enterprise Java applications.

Arquillian persistence extension allows you to test JPA related code without filling up the database with test data. All you have to do is to populate .yml file with your data specified. That will be best described with an example.

First of all add arquillian persistence dependencies to your project:

<dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-persistence-api</artifactId>
            <version>${version.arquillian_persistence}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-persistence-impl</artifactId>
            <version>${version.arquillian_persistence}</version>
            <scope>test</scope>
        </dependency>

where ‘${version.arquillian_persistence}’ is equal to ‘1.0.0.Alpha2’. I assume that you have the basic arquillian tests (for EJB’s and CDI) working, If not read on.

I have found myself setting up arquillian enabled project quite cumbersome, always ending up with some classpath dependency problems while trying to remote test my classes. For those of you new to Arquillian I would strongly recommend starting up with working example provided by Bartosz Majsak and available on github as a ‘Beer-Advisor‘ project.

The ‘Beer-Advisor’ project can be quickly refactored to suit your needs, it lack comments but its so clearly written that it shouldn’t be a problem to grasp the idea.

Ok then, lets get going with the arquillian persistence extension, we are going to use two nice annotations to help us testing our JPA layer: @UsingDataSet and @ShouldMatchDataSet.

We start off with doing some setup, I will copy part of the example from the Beer-Advisor project which you can easily clone and try for yourself:

Having an entity class Beer:

@Entity
public class Beer implements Serializable
{
   private static final long serialVersionUID = 5892013208071126314L;

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private Long id;

   @Basic
   private String name;

   @Basic
   private BigDecimal price;

   @Basic
   private BigDecimal alcohol;

   @Basic
   private String code;

   @Enumerated(EnumType.STRING)
   private Type type;

   // If lazy then Glassfish Embedded is facing this problem: https://bugs.eclipse.org/bugs/show_bug.cgi?id=323403
   @ManyToOne(optional = false, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
   private Brewery brewery;

   Beer()
   {
      // to satisfy JPA
   }

   public Beer(Brewery brewery, Type type, String name, BigDecimal price, BigDecimal alcohol)
   {
      this.name = name;
      this.price = price;
      this.alcohol = alcohol;
      this.type = type;
      this.brewery = brewery;
      this.brewery.addBeer(this);
   }
........ Getters and Setters ...............

and simple DAO for managing Beer objects on the persistence layer:

@RequestScoped
public class JpaBeerRepository implements BeerRepository
{
   @PersistenceContext
   private EntityManager em;

   @Override
   public Beer getById(Long id)
   {
      return em.find(Beer.class, id);
   }
..........

@Override
   public Set<Beer> fetchAll()
   {
      CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
      CriteriaQuery<Beer> query = criteriaBuilder.createQuery(Beer.class);
      Root<Beer> from = query.from(Beer.class);
      CriteriaQuery<Beer> select = query.select(from);

      Set<Beer> result = new HashSet<Beer>();
      result.addAll(em.createQuery(select).getResultList());

      return result;
   }

   @Override
   public void save(Beer beer)
   {
      if (beer.getId() == null)
      {
         em.persist(beer);
      }
      else
      {
         em.merge(beer);
      }
   }
..................

We can easily test our DAO by creating datasets in yml format and test our logic against it:

Beer:
  - id: 1
    alcohol: 4.5
    name: "Mocny Full"
    price: 1.0
    type: LAGER
    brewery_id: 1
  - id: 2
    alcohol: 55.0
    name: "End of history"
    price: 765
    type: BLOND_ALE
    brewery_id: 2
  - id: 3
    alcohol: 41.0
    name: "Sink The Bismarck!"
    price: 64.0
    type: QUADRUPEL_IPA
    brewery_id: 2
  - id: 4
    alcohol: 8.5
    name: "Delirium Tremens"
    price: 10.0
    type: PALE_ALE
    brewery_id: 3
  - id: 5
    alcohol: 8.4
    name: "Pauwel Kwak"
    price: 4.0
    type: AMBER
    brewery_id: 4

You should put your .yml file into test/resources/datasets folder in you maven project

@UsingDataSet annotation will populate our database with the data specified in beers.yml file

   @Test
   @UsingDataSet("beers.yml")
   public void shouldReturnBeerByItsId() throws Exception
   {
      // given
      Long beerId = 1L;
      String expectedName = "Mocny Full";

      // when
      Beer beers = beerRepository.getById(beerId);

      // then
      assertThat(beers.getName()).isEqualTo(expectedName);
   }

Now, lets say we want to add new Beer and see if the database will have a specific data in it, for this purpose we are going to use @ShouldMatchDataSet(..)

@Test
    @ShouldMatchDataSet("expected-insert-beer.yml")
    public void shouldSaveNewBeer() throws Exception{
        //when
        Beer b = new Beer();
                //set the necessary fields on the beer object
        beerRepository.save(b);
        assertThat(beerRepository).isNotNull();
    }

after inserting our Beer object to the database through the EntityManager we should end up with a single beer record in our database, exactly like the one specified in ‘expected-insert-beer.yml’.