Integration Tests with Arquillian using TomEE

by Hayri Cicek


Posted on 03-Sep-2018

In this tutorial we will learn how to integrate tests with Arquillian using TomEE Application Server.

Tools You Will Need
Maven 3.3+
Your favorite IDE
JDK 1.8+
Git

Clone the TomEE Starter Project from Github

$ git clone https://github.com/cicekhayri/tomee-javaee-crud-rest-starter-project.git
Now it's time to add some dependencies.
Open the project in your favorite IDE and add the following to the pom.xml

<dependency>
    <groupId>org.jboss.shrinkwrap.resolver</groupId>
    <artifactId>shrinkwrap-resolver-depchain</artifactId>
    <version>3.1.3</version>
    <scope>test</scope>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>org.apache.tomee</groupId>
    <artifactId>arquillian-tomee-remote</artifactId>
    <version>${tomee.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.jboss.arquillian.junit</groupId>
    <artifactId>arquillian-junit-container</artifactId>
    <scope>test</scope>
    <version>1.4.0.Final</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.tomee</groupId>
    <artifactId>tomee-jaxrs</artifactId>
    <version>${tomee.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

We added Arquillian dependencies and your pom.xml should look like this now :


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.kodnito</groupId>
    <artifactId>restapi</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <tomee.version>7.0.5</tomee.version>
        <javaee.api>7.0</javaee.api>
        <jackson.version>2.9.6</jackson.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>${javaee.api}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.196</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>eclipselink</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.shrinkwrap.resolver</groupId>
            <artifactId>shrinkwrap-resolver-depchain</artifactId>
            <version>3.1.3</version>
            <scope>test</scope>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.apache.tomee</groupId>
            <artifactId>arquillian-tomee-remote</artifactId>
            <version>${tomee.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
            <version>1.4.0.Final</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomee</groupId>
            <artifactId>tomee-jaxrs</artifactId>
            <version>${tomee.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.tomee.maven</groupId>
                <artifactId>tomee-maven-plugin</artifactId>
                <version>${tomee.version}</version>
                <configuration>
                    <tomeeVersion>${tomee.version}</tomeeVersion>
                    <tomeeClassifier>plus</tomeeClassifier>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


In project directory run the following command to download the dependencies.


$ mvn install


Arquillian Tests

Inside src/test/java/com/kodnito/it/rest/ package create TodoEndpoint.java and add the following :


package com.kodnito.it.rest;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kodnito.restapi.entity.Todo;
import java.io.File;
import java.net.URL;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.junit.Assert;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;


@RunWith(Arquillian.class)
public class TodoEndpointTest {

    @ArquillianResource
    private URL webappUrl;

    WebTarget target;

    ObjectMapper om = new ObjectMapper();

    @Before
    public void before() throws Exception {
        target = ClientBuilder.newClient().target(webappUrl.toURI()).path("api");
    }

    @Deployment
    public static WebArchive createDeployment() {
        File[] files = Maven.resolver().loadPomFromFile("pom.xml")
                .importRuntimeDependencies().resolve().withTransitivity().asFile();

        WebArchive war = ShrinkWrap.create(WebArchive.class)
                .addAsLibraries(files)
                .addPackages(true, "com.kodnito.restapi")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
                .addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml");

        System.out.println(war.toString(true));

        return war;
    }

    @Test
    @InSequence(1)
    @RunAsClient
    public void shouldCreateTodo() throws Exception {
        Todo todo = new Todo();
        todo.setTask("this is task");
        todo.setDescription("this is description");

        String todoJsonString = om.writeValueAsString(todo);

        final Response response = target
                .path("todos")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(todoJsonString));

        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
    }

    @Test
    @InSequence(2)
    @RunAsClient
    public void shouldGetAllTodos() throws Exception {
        final Response response = target.path("todos")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .get();

        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());

        JsonNode json = om.readTree(response.readEntity(String.class));

        Assert.assertTrue(json.size() > 0);
    }

    @Test
    @InSequence(3)
    @RunAsClient
    public void shouldGetByTodoId() throws Exception {
        final Response response = target.path("todos")
                .path("1")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .get();

        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());

        JsonNode json = om.readTree(response.readEntity(String.class));

        assertNotNull("Response contains id ", json.get("id").asLong());
        assertEquals(1L, json.get("id").asLong());
    }

    @Test
    @InSequence(4)
    @RunAsClient
    public void shouldPut() throws Exception {

        Todo todo = new Todo();
        todo.setId(1L);
        todo.setTask("this is updated task");
        todo.setDescription("this is updated description");

        String todoUpdateString = om.writeValueAsString(todo);

        final Response response = target.path("todos")
                .path("1")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .put(Entity.json(todoUpdateString));

        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
    }

    @Test
    @InSequence(5)
    @RunAsClient
    public void shouldDelete() throws Exception {
        final Response response = target.path("todos")
                .path("1")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .delete();

        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
    }

}


@RunWith(Arquillian.class) annotation tells JUnit to use Arquillian as controller.
@ArquillianResource annotation will inject url and only works on in-container tests.
@Deployment annotation is used to define which methods should be considered as deployment producer.
@Test annotation tells JUnit that the method can be run as a test case.
@InSequence annotation is used to order the execution flow of the @Test methods
@RunAsClient annotation will execute the test methods on the client side.
om.writeValueAsString() methods is used to serialize any Java value as a String.
om.readTree() method will parse JSON content into JsonNode object.
assertEquals() checks that two objects are equal.
assertNotNull() checks that an object is not null.
Assert.assertTrue() checks that condition is true.
shouldCreateTodo() method tests the creation of creating Todo object.
shouldGetAllTodos() method tests to get a list of todos.
shouldGetByTodoId() method tests getting Todo object by id.
shouldPut() method tests updating Todo object.
shouldDelete() method tests deleting of Todo object.

Your project structure should look like this

tree .
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── kodnito
    │   │           └── restapi
    │   │               ├── entity
    │   │               │   └── Todo.java
    │   │               ├── rest
    │   │               │   ├── ApplicationConfig.java
    │   │               │   └── TodoEndpoint.java
    │   │               └── service
    │   │                   └── TodoService.java
    │   ├── resources
    │   │   └── META-INF
    │   │       └── persistence.xml
    │   └── webapp
    │       └── WEB-INF
    │           ├── beans.xml
    │           └── resources.xml
    └── test
        ├── java
        │   └── com
        │       └── kodnito
        │           └── it
        │               └── rest
        │                   └── TodoEndpointTest.java
        └── resources
            └── arquillian.xml

Now in the project directory run the following command :

$ mvn clean test


In this tutorial we learned how to integrate test with Arquillian and TomEE.
Clone the final project from GitHub

$ git clone https://github.com/cicekhayri/tomee-javaee-crud-rest-arquillian-project.git


Share this: