Kohei Nozaki's blog 

Arquillian Persistence Extension examples


Posted on Wednesday Mar 18, 2015 at 05:47PM in Arquillian


The whole project can be obtained from GitHub. tested with WildFly 8.2.0.Final as remote container.

Implementation (test target)

Assume we have very simple 2 entities as follows:

@Entity
public class Dept implements Serializable {
    @Id
    private Integer id;
    @Column(nullable = false)
    private String name;
    @OneToMany(mappedBy = "dept")
    private Collection<Employee> employees;
...

@Entity
public class Employee implements Serializable {
    @Id
    private Integer id;
    @Column(nullable = false)
    private String name;
    @JoinColumn(nullable = false)
    @ManyToOne
    private Dept dept;
...

Test target EJB:

@Stateless
@LocalBean
public class HumanResourcesBean {

    @PersistenceContext
    private EntityManager em;

    public void addEmployee(Employee employee, Integer deptId) {
        final Dept dept = em.find(Dept.class, deptId);
        dept.getEmployees().add(employee);
        employee.setDept(dept);
        em.persist(employee);
    }

    public void addDept(Dept dept, Employee employee) {
        Collection<Employee> employees = new ArrayList<>();
        dept.setEmployees(employees);
        employees.add(employee);
        employee.setDept(dept);
        em.persist(dept);
        em.persist(employee);
    }
}

addEmployee() testing

Test method of addEmployee():

@Test
@UsingDataSet("input.xml")
@ShouldMatchDataSet(value = "addEmployee-expected.xml", orderBy = "id")
public void addEmployeeTest() throws Exception {
    Employee emp = new Employee();
    emp.setId(2002);
    emp.setName("Todd");
    humanResourcesBean.addEmployee(emp, 200);
}

Initial entry data (input.xml):

<dataset>
    <Dept id="100" name="Sales"/>
    <Dept id="200" name="Finance"/>
    <Employee id="1000" name="Scott"  dept_id="100"/>
    <Employee id="1001" name="Martin" dept_id="100"/>
    <Employee id="1002" name="Nick"   dept_id="100"/>
    <Employee id="2000" name="Jordan" dept_id="200"/>
    <Employee id="2001" name="David"  dept_id="200"/>
</dataset>

Expected data (addEmployee-expected.xml):

<dataset>
    <Employee id="1000" name="Scott"  dept_id="100"/>
    <Employee id="1001" name="Martin" dept_id="100"/>
    <Employee id="1002" name="Nick"   dept_id="100"/>
    <Employee id="2000" name="Jordan" dept_id="200"/>
    <Employee id="2001" name="David"  dept_id="200"/>
    <Employee id="2002" name="Todd"   dept_id="200"/> <!-- Newly added -->
</dataset>

addDept() testing

Test method of addDept():

@Test
@UsingDataSet("input.xml")
@ShouldMatchDataSet(value = "addDept-expected.xml", orderBy = "id")
public void addDeptTest() throws Exception {
    Dept dept = new Dept();
    dept.setId(300);
    dept.setName("Engineering");
    Employee emp = new Employee();
    emp.setId(3000);
    emp.setName("Carl");
    humanResourcesBean.addDept(dept, emp);
}

Initial entry data (input.xml) is the same to previous testing.

Expected data (addDept-expected.xml):

<dataset>
    <Dept id="100" name="Sales"/>
    <Dept id="200" name="Finance"/>
    <Dept id="300" name="Engineering"/> <!-- Newly added -->
    <Employee id="1000" name="Scott"  dept_id="100"/>
    <Employee id="1001" name="Martin" dept_id="100"/>
    <Employee id="1002" name="Nick"   dept_id="100"/>
    <Employee id="2000" name="Jordan" dept_id="200"/>
    <Employee id="2001" name="David"  dept_id="200"/>
    <Employee id="3000" name="Carl"   dept_id="300"/> <!-- Newly added -->
</dataset>

It works well with multiple tables.

addDept() testing with DBUnit

Sometimes use of DBUnit directly is useful for complex assertion. in such case you need to care following conditions:

  • If you use JPA, force EntityManager to execute DMLs via invoking em.flush() before assertion

  • Include test data to the Arquillian’s application archive so that DBUnit can load these data on the server side

The XML can be included via addAsResource() method as follows:

@Deployment
public static Archive<?> createDeploymentPackage() {
    final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war")
            .addPackage(Dept.class.getPackage())
            .addClass(HumanResourcesBean.class)
            .addAsResource("datasets/addDept-expected.xml") // to be loaded by DBUnit on the server side
            .addAsResource("test-persistence.xml", "META-INF/persistence.xml");
//        System.out.println(webArchive.toString(true));
    return webArchive;
}

The test method of addDept() and related convenient methods:

@Test
@UsingDataSet("input.xml")
public void addDeptTestWithDbUnit() throws Exception {
    Dept dept = new Dept();
    dept.setId(300);
    dept.setName("Engineering");
    Employee emp = new Employee();
    emp.setId(3000);
    emp.setName("Carl");

    humanResourcesBean.addDept(dept, emp);
    em.flush(); // force JPA to execute DMLs before assertion

    final IDataSet expectedDataSet = getDataSet("/datasets/addDept-expected.xml");
    assertTable(expectedDataSet.getTable("Dept"), "select * from dept order by id");
    assertTable(expectedDataSet.getTable("Employee"), "select * from employee order by id");
}

private static IDataSet getDataSet(String path) throws DataSetException {
    return new FlatXmlDataSetBuilder().build(HumanResourcesBeanIT.class.getResource(path));
}

private void assertTable(ITable expectedTable, String sql) throws SQLException, DatabaseUnitException {
    try (Connection cn = ds.getConnection()) {
        IDatabaseConnection icn = null;
        try {
            icn = new DatabaseConnection(cn);
            final ITable queryTable = icn.createQueryTable(expectedTable.getTableMetaData().getTableName(), sql);
            Assertion.assertEquals(expectedTable, queryTable);
        } finally {
            if (icn != null) {
                icn.close();
            }
        }
    }
}