Testing microservices with the Arquillian managed container

duration 15 minutes


Learn how to develop tests for your microservices with the Arquillian managed container and run the tests on Open Liberty.

What you’ll learn

You will learn how to develop tests for your microservices by using the Arquillian Liberty Managed container and JUnit with Maven on Open Liberty. Arquillian is a testing framework to develop automated functional, integration and acceptance tests for your Java applications. Arquillian sets up the test environment and handles the application server lifecycle for you so you can focus on writing tests.

You will develop Arquillian tests that use JUnit as the runner and build your tests with Maven using the Liberty Maven plug-in. This technique simplifies the process of managing Arquillian dependencies and the setup of your Arquillian managed container.

You will work with an inventory microservice, which stores information about various systems. The inventory service communicates with the system service on a particular host to retrieve its system properties and store them. You will develop functional and integration tests for the microservices. You will also learn about the Maven and server configurations so that you can run your tests on Open Liberty with the Arquillian Liberty Managed container.

Getting started

The fastest way to work through this guide is to clone the Git repository and use the projects that are provided inside:

git clone https://github.com/openliberty/guide-arquillian-managed.git
cd guide-arquillian-managed

The start directory contains the starting project that you will build upon.

The finish directory contains the finished project that you will build.

Try what you’ll build

To try out the finished Arquillian tests, first navigate to the finish directory and then run the following Maven goal to build the application and run the tests on Open Liberty:

mvn install

In the console output, you can see that the build was successful and the tests passed.

Developing Arquillian tests

Navigate to the start directory to begin.

You’ll develop tests that use Arquillian and JUnit to verify the inventory microservice as an endpoint and the functions of the InventoryResource class. The code for the microservices is in the src/main/java/io/openliberty/guides directory.

Create the InventoryArquillianTests test class.


 1package it.io.openliberty.guides.inventory;
 3import java.net.URL;
 4import java.util.List;
 6import javax.inject.Inject;
 7import javax.json.JsonObject;
 8import javax.ws.rs.client.Client;
 9import javax.ws.rs.client.ClientBuilder;
10import javax.ws.rs.client.WebTarget;
11import javax.ws.rs.core.Response;
13import org.apache.cxf.jaxrs.provider.jsrjsonp.JsrJsonpProvider;
14import org.jboss.arquillian.container.test.api.Deployment;
15import org.jboss.arquillian.container.test.api.RunAsClient;
16import org.jboss.arquillian.junit.Arquillian;
17import org.jboss.arquillian.junit.InSequence;
18import org.jboss.arquillian.test.api.ArquillianResource;
19import org.jboss.shrinkwrap.api.ShrinkWrap;
20import org.jboss.shrinkwrap.api.spec.WebArchive;
21import org.junit.Assert;
22import org.junit.Test;
23import org.junit.runner.RunWith;
25import io.openliberty.guides.inventory.InventoryResource;
26import io.openliberty.guides.inventory.model.InventoryList;
27import io.openliberty.guides.inventory.model.SystemData;
30public class InventoryArquillianTests {
32    private final static String WARNAME = "arquillian-managed.war";
33    private final String INVENTORY_SYSTEMS = "inventory/systems";
34    private Client client = ClientBuilder.newClient();
36    @Deployment(testable = true)
37    public static WebArchive createDeployment() {
38        WebArchive archive = ShrinkWrap.create(WebArchive.class, WARNAME)
39                                       .addPackages(true, "io.openliberty.guides");
40        return archive;
41    }
43    @ArquillianResource
44    private URL baseURL;
46    @Inject
47    InventoryResource invSrv;
49    @Test
50    @RunAsClient
51    @InSequence(1)
52    public void testInventoryEndpoints() throws Exception {
53        String localhosturl = baseURL + INVENTORY_SYSTEMS + "/localhost";
55        client.register(JsrJsonpProvider.class);
56        WebTarget localhosttarget = client.target(localhosturl);
57        Response localhostresponse = localhosttarget.request().get();
59        Assert.assertEquals("Incorrect response code from " + localhosturl, 200,
60                            localhostresponse.getStatus());
62        JsonObject localhostobj = localhostresponse.readEntity(JsonObject.class);
63        Assert.assertEquals("The system property for the local and remote JVM "
64                        + "should match", System.getProperty("os.name"),
65                            localhostobj.getString("os.name"));
67        String invsystemsurl = baseURL + INVENTORY_SYSTEMS;
69        WebTarget invsystemstarget = client.target(invsystemsurl);
70        Response invsystemsresponse = invsystemstarget.request().get();
72        Assert.assertEquals("Incorrect response code from " + localhosturl, 200,
73                            invsystemsresponse.getStatus());
75        JsonObject invsystemsobj = invsystemsresponse.readEntity(JsonObject.class);
77        int expected = 1;
78        int actual = invsystemsobj.getInt("total");
79        Assert.assertEquals("The inventory should have one entry for localhost",
80                            expected, actual);
81        localhostresponse.close();
82    }
84    @Test
85    @InSequence(2)
86    public void testInventoryResourceFunctions() {
88        // Listing the inventory contents that were stored in the previous test
89        InventoryList invList = invSrv.listContents();
90        Assert.assertEquals(1, invList.getTotal());
92        List<SystemData> systemDataList = invList.getSystems();
93        Assert.assertTrue(systemDataList.get(0).getHostname().equals("localhost"));
95        Assert.assertTrue(systemDataList.get(0).getProperties().get("os.name")
96                                        .equals(System.getProperty("os.name")));
97    }

Notice that the JUnit Arquillian runner runs the tests instead of the standard JUnit runner. The @RunWith annotation preceding the class tells JUnit to run the tests by using Arquillian.

The method annotated by @Deployment defines the content of the web archive, which is going to be deployed onto the Open Liberty server. The tests are either run on or against the server. The testable = true attribute enables the deployment to run the tests "in container", that is the tests are run on the server.

Notice the arquillian-managed.war name that is used for the web archive. This name is necessary if you don’t want a randomly generated web archive name.

The ShrinkWrap API is used to create the web archive. All of the packages in the inventory service must be added to the web archive; otherwise, the code compiles successfully but fails at runtime when the injection of the InventoryResource class takes place. You can learn about the ShrinkWrap archive configuration in this Arquillian guide.

The @ArquillianResource annotation is used to retrieve the http://localhost:9080/arquillian-managed/ base URL for this web service. The annotation provides the host name, port number and web archive information for this service, so you don’t need to hardcode these values in the test case. The arquillian-managed path in the URL comes from the WAR name you specified when you created the web archive in the @Deployment annotated method. It’s needed when the inventory service communicates with the system service to get the system properties.

The testInventoryEndpoints method is an integration test to test the inventory service endpoints. The @RunAsClient annotation added in this test case indicates that this test case is to be run on the client side. By running the tests on the client side, the tests are run against the managed container. The endpoint test case first calls the http://localhost:9080/{WARNAME}/inventory/systems/{hostname} endpoint with the localhost host name to add its system properties to the inventory. The test verifies that the system property for the local and service JVM match. Then, the test method calls the http://localhost:9080/{WARNAME}/inventory/systems endpoint. The test checks that the inventory has one host and that the host is localhost. The test also verifies that the system property stored in the inventory for the local and service JVM match.

Contexts and Dependency Injection (CDI) is used to inject an instance of the InventoryResource class into this test class. You can learn more about CDI in the Injecting dependencies into microservices guide.

The injected InventoryResource instance is then tested by the testInventoryResourceFunctions method. This test case calls the listContents() method to get all systems that are stored in this inventory and verifies that localhost is the only system being found. Notice the functional test case doesn’t store any system in the inventory, the localhost system is from the endpoint test case that ran before this test case. The @InSequence Arquillian annotation guarantees the test sequence. The sequence is important for the two tests, as the results in the first test impact the second one.

The test cases are ready to run. You will configure the Maven build and the Liberty application server to run them.

Configuring Arquillian with Liberty

Configure your build to use the Arquillian Liberty Managed container and set up your Open Liberty server to run your test cases by configuring the server.xml file.

Configuring your test build

First, configure your test build with Maven. All of the Maven configuration takes place in the pom.xml file, which is provided for you.


  1<?xml version="1.0" encoding="UTF-8"?>
  2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5    <modelVersion>4.0.0</modelVersion>
  7    <parent>
  8        <groupId>net.wasdev.wlp.maven.parent</groupId>
  9        <artifactId>liberty-maven-app-parent</artifactId>
 10        <version>RELEASE</version>
 11    </parent>
 13    <groupId>io.openliberty.guides</groupId>
 14    <artifactId>microservices-arquillian-managed-test</artifactId>
 15    <version>1.0-SNAPSHOT</version>
 16    <packaging>war</packaging>
 18    <properties>
 19        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 20        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 21        <maven.compiler.source>1.8</maven.compiler.source>
 22        <maven.compiler.target>1.8</maven.compiler.target>
 23        <app.name>LibertyProject</app.name>
 24        <testServerHttpPort>9080</testServerHttpPort>
 25        <testServerHttpsPort>9443</testServerHttpsPort>
 26        <package.file>${project.build.directory}/${app.name}.zip</package.file>
 27        <packaging.type>usr</packaging.type>
 28    </properties>
 30    <dependencyManagement>
 31        <dependencies>
 32            <dependency>
 33                <groupId>io.openliberty.features</groupId>
 34                <artifactId>features-bom</artifactId>
 35                <version>RELEASE</version>
 36                <type>pom</type>
 37                <scope>import</scope>
 38            </dependency>
 39            <dependency>
 40                <groupId>org.jboss.arquillian</groupId>
 41                <artifactId>arquillian-bom</artifactId>
 42                <version>1.4.0.Final</version>
 43                <type>pom</type>
 44                <scope>import</scope>
 45            </dependency>
 46        </dependencies>
 47    </dependencyManagement>
 49    <dependencies>
 50        <!-- For tests -->
 51        <dependency>
 52            <groupId>junit</groupId>
 53            <artifactId>junit</artifactId>
 54            <version>4.12</version>
 55            <scope>test</scope>
 56        </dependency>
 57        <dependency>
 58            <groupId>org.apache.cxf</groupId>
 59            <artifactId>cxf-rt-rs-client</artifactId>
 60            <version>3.1.11</version>
 61            <scope>test</scope>
 62        </dependency>
 63        <dependency>
 64            <groupId>org.apache.cxf</groupId>
 65            <artifactId>cxf-rt-rs-extension-providers</artifactId>
 66            <version>3.1.11</version>
 67            <scope>test</scope>
 68        </dependency>
 69        <dependency>
 70            <groupId>org.glassfish</groupId>
 71            <artifactId>javax.json</artifactId>
 72            <version>1.0.4</version>
 73            <scope>test</scope>
 74        </dependency>
 75        <!-- Open Liberty features -->
 76        <dependency>
 77            <groupId>io.openliberty.features</groupId>
 78            <artifactId>jaxrs-2.1</artifactId>
 79            <type>esa</type>
 80            <scope>provided</scope>
 81        </dependency>
 82        <dependency>
 83            <groupId>io.openliberty.features</groupId>
 84            <artifactId>jsonp-1.1</artifactId>
 85            <type>esa</type>
 86            <scope>provided</scope>
 87        </dependency>
 88        <dependency>
 89            <groupId>io.openliberty.features</groupId>
 90            <artifactId>cdi-2.0</artifactId>
 91            <type>esa</type>
 92            <scope>provided</scope>
 93        </dependency>
 94        <!-- For JDK 9 & above Support -->
 95        <dependency>
 96            <groupId>javax.xml.bind</groupId>
 97            <artifactId>jaxb-api</artifactId>
 98            <version>2.2.11</version>
 99        </dependency>
100        <dependency>
101            <groupId>com.sun.xml.bind</groupId>
102            <artifactId>jaxb-core</artifactId>
103            <version>2.2.11</version>
104        </dependency>
105        <dependency>
106            <groupId>com.sun.xml.bind</groupId>
107            <artifactId>jaxb-impl</artifactId>
108            <version>2.2.11</version>
109        </dependency>
110        <dependency>
111            <groupId>javax.activation</groupId>
112            <artifactId>activation</artifactId>
113            <version>1.1.1</version>
114        </dependency>
115        <dependency>
116            <groupId>io.openliberty.arquillian</groupId>
117            <artifactId>arquillian-liberty-managed-junit</artifactId>
118            <version>1.1.6</version>
119            <type>pom</type>
120            <scope>test</scope>
121        </dependency>
122        <dependency>
123            <groupId>org.jboss.shrinkwrap</groupId>
124            <artifactId>shrinkwrap-api</artifactId>
125            <scope>test</scope>
126        </dependency>
127    </dependencies>
129    <build>
130        <plugins>
131            <plugin>
132                <groupId>org.apache.maven.plugins</groupId>
133                <artifactId>maven-war-plugin</artifactId>
134                <version>3.2.2</version>
135                <configuration>
136                    <failOnMissingWebXml>false</failOnMissingWebXml>
137                    <packagingExcludes>pom.xml</packagingExcludes>
138                </configuration>
139            </plugin>
140            <plugin>
141                <groupId>org.apache.maven.plugins</groupId>
142                <artifactId>maven-failsafe-plugin</artifactId>
143                <version>3.0.0-M1</version>
144                <executions>
145                    <execution>
146                        <id>failsafe-integration-test</id>
147                        <phase>integration-test</phase>
148                        <goals>
149                            <goal>integration-test</goal>
150                        </goals>
151                        <configuration>
152                            <includes>
153                                <include>**/it/**/*.java</include>
154                            </includes>
155                        </configuration>
156                    </execution>
157                    <execution>
158                        <id>failsafe-verify</id>
159                        <phase>verify</phase>
160                        <goals>
161                            <goal>verify</goal>
162                        </goals>
163                    </execution>
164                </executions>
165                <configuration>
166                    <summaryFile>
167                      ${project.build.directory}/test-reports/it/failsafe-summary.xml
168                    </summaryFile>
169                    <reportsDirectory>
170                      ${project.build.directory}/test-reports/it
171                    </reportsDirectory>
172                </configuration>
173            </plugin>
174            <plugin>
175                <groupId>net.wasdev.wlp.maven.plugins</groupId>
176                <artifactId>liberty-maven-plugin</artifactId>
177                <extensions>true</extensions>
178                <!-- Specify configuration, executions for liberty-maven-plugin -->
179                <configuration>
180                    <serverName>ArquillianManagedServer</serverName>
181                    <assemblyArtifact>
182                        <groupId>io.openliberty</groupId>
183                        <artifactId>openliberty-runtime</artifactId>
184                        <version>[,)</version>
185                        <type>zip</type>
186                    </assemblyArtifact>
187                    <configFile>src/main/liberty/config/server.xml</configFile>
188                    <packageFile>${package.file}</packageFile>
189                    <include>${packaging.type}</include>
190                    <bootstrapProperties>
191                        <default.http.port>${testServerHttpPort}</default.http.port>
192                        <default.https.port>${testServerHttpsPort}</default.https.port>
193                    </bootstrapProperties>
194                    <skipTestServer>true</skipTestServer>
195                </configuration>
196                <executions>
197                    <execution>
198                        <id>install-apps</id>
199                        <configuration>
200                            <looseApplication>true</looseApplication>
201                            <stripVersion>true</stripVersion>
202                            <installAppPackages>project</installAppPackages>
203                        </configuration>
204                    </execution>
205                    <execution>
206                        <id>package-app</id>
207                        <configuration>
208                            <outputDirectory>target/wlp-package</outputDirectory>
209                        </configuration>
210                    </execution>
211                    <execution>
212                        <id>configure-arquillian-xml</id>
213                        <phase>pre-integration-test</phase>
214                        <goals>
215                            <goal>configure-arquillian</goal>
216                        </goals>
217                    </execution>
218                </executions>
219            </plugin>
220        </plugins>
221    </build>

Let’s look into each of the required elements for this configuration. You need the liberty-maven-app-parent block, which configures the Liberty Maven plug-in with the default executions necessary for setting up your managed Liberty server.

You also need the arquillian-bom Bill of Materials. It’s a Maven artifact that defines the versions of Arquillian dependencies to make dependency management easier.

The arquillian-liberty-managed-junit dependency bundle, which includes all the core dependencies, is required to run the Arquillian tests on a managed Liberty container that uses JUnit. You can learn more about the Arquillian Liberty dependency bundles. The shrinkwrap-api dependency allows you to create your test archive, which is packaged into a WAR file and deployed to the Open Liberty server.

The maven-failsafe-plugin artifact runs your Arquillian integration tests by using JUnit.

Lastly, specify the liberty-maven-plugin configuration that defines your Open Liberty runtime configuration and use the configure-arquillian goal to configure your Arquillian container. This goal automatically retrieves core server parameters from the liberty-maven-plugin configuration and enables you to customize your Arquillian container configuration directly in your POM file if necessary. You can learn more about the configure-arquillian goal in its documentation.

Notice in the liberty-maven-plugin configuration that the skipTestServer element is set to true to skip the test-start-server and test-stop-server goals defined in the liberty-maven-app-parent parent configuration. The test server configuration is skipped because Arquillian is managing the server lifecycle when it runs the tests.

Configuring the server.xml file

Now that you’re done configuring your Maven build, set up your Open Liberty server to run your test cases by configuring the server.xml file.

Take a look at the server.xml file.


 1<server description="new server">
 3  <featureManager>
 4    <feature>jaxrs-2.1</feature>
 5    <feature>jsonp-1.1</feature>
 6    <feature>cdi-2.0</feature>
 8    <!-- Enable the following features to run tests with Arquillian managed container -->
 9    <feature>localConnector-1.0</feature>
10    <feature>servlet-4.0</feature>
11  </featureManager>
13  <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443" />
14  <webApplication location="microservices-arquillian-managed-test.war" context-root="/"/>

The localConnector feature is required by the Arquillian Liberty Managed container to connect to and communicate with the Open Liberty runtime. The servlet feature is required during the deployment of the Arquillian tests in which servlets are created to perform the in-container testing.

Running the tests

It’s now time to build and run your Arquillian tests. Run the Maven build command in the start directory.

mvn install

In the test output, you can see that the application server launched, and that the web archive, arquillian-managed, started as an application in the server. You can also see that the tests are running and that the results are reported.

After the tests stop running, the test application is automatically undeployed and the server shuts down. You should then get a message indicating that the build and tests are successful.

[INFO] -------------------------------------------------------
[INFO] -------------------------------------------------------
[INFO] Running it.io.openliberty.guides.inventory.InventoryArquillianTests
[AUDIT   ] CWWKE0001I: The server ArquillianManagedServer has been launched.
[INFO    ] CWWKE0002I: The kernel started after 2.069 seconds
[INFO    ] CWWKF0007I: Feature update started.
[AUDIT   ] CWWKZ0058I: Monitoring dropins for applications.
[INFO    ] CWWKO0219I: TCP Channel defaultHttpEndpoint has been started and is now listening for requests on host localhost  (IPv4: port 9080.
[INFO    ] CWWKZ0018I: Starting application microservices-arquillian-managed-test.
[INFO    ] SRVE0169I: Loading Web Module: microservices-arquillian-managed-test.
[INFO    ] SRVE0250I: Web Module microservices-arquillian-managed-test has been bound to default_host.
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://localhost:9080/
[AUDIT   ] CWWKZ0001I: Application microservices-arquillian-managed-test started in 4.276 seconds.
[INFO    ] SESN0176I: A new session context will be created for application key default_host/
[INFO    ] CWWKZ0018I: Starting application arquillian-managed.
[AUDIT   ] CWWKF0011I: The server ArquillianManagedServer is ready to run a smarter planet.
[INFO    ] SRVE0169I: Loading Web Module: arquillian-managed.
[INFO    ] SRVE0250I: Web Module arquillian-managed has been bound to default_host.
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://localhost:9080/arquillian-managed/
[AUDIT   ] CWWKZ0001I: Application arquillian-managed started in 0.957 seconds.
[INFO    ] Setting the server's publish address to be /inventory/
[INFO    ] SRVE0242I: [arquillian-managed] [/arquillian-managed] [io.openliberty.guides.inventory.InventoryApplication]: Initialization successful.
[INFO    ] Setting the server's publish address to be /system/
[INFO    ] SRVE0242I: [microservices-arquillian-managed-test] [/] [io.openliberty.guides.system.SystemApplication]: Initialization successful.
[INFO    ] SRVE0242I: [arquillian-managed] [/arquillian-managed] [ArquillianServletRunner]: Initialization successful.
[AUDIT   ] CWWKT0017I: Web application removed (default_host): http://localhost:9080/arquillian-managed/
[INFO    ] SRVE0253I: [arquillian-managed] [/arquillian-managed] [ArquillianServletRunner]: Destroy successful.
[INFO    ] SRVE0253I: [arquillian-managed] [/arquillian-managed] [io.openliberty.guides.inventory.InventoryApplication]: Destroy successful.
[AUDIT   ] CWWKZ0009I: The application arquillian-managed has stopped successfully.
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 15.355 s - in it.io.openliberty.guides.inventory.InventoryArquillianTests
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  25.875 s
[INFO] Finished at: 2019-02-12T14:40:43-05:00
[INFO] ------------------------------------------------------------------------

Great work! You’re done!

You just built some functional and integration tests with the Arquillian managed container and ran the tests for your microservices on Open Liberty.

Try one of the related guides to learn more about the technologies that you come across in this guide.

Guide Attribution

Testing microservices with the Arquillian managed container by Open Liberty is licensed under CC BY-ND 4.0

Copied to clipboard
Copy code block
Copy file contents


Nice work! Where to next?

What did you think of this guide?

Extreme Dislike Dislike Like Extreme Like

What could make this guide better?

Raise an issue to share feedback

Create a pull request to contribute to this guide

Need help?

Ask a question on Stack Overflow

Like Open Liberty? Star our repo on GitHub.