Write and execute a JUnit test for a Java microservice based on MicroProfile and run both in the OpenLiberty development mode
Tags: java, junit, visualstudiocode, microprofile
Published: 2020-03-17 17:28:02

---
title: Write and execute a JUnit test for a Java microservice based on MicroProfile and run both in the OpenLiberty development mode
published: true
description: That blog post has the focus on: how to develop a JUnit test for the Authors microservice from the Cloud Native Starter example and run both the Authors microservice and the JUnit test on OpenLiberty in the development mode.
tags: java, junit, visualstudiocode, microprofile
cover_image: https://suedbroecker.files.wordpress.com/2020/03/software-762486_1920.jpg?w=820&h=312&crop=1
---

That post has the focus on: how to develop a JUnit test for the Authors microservice from the Cloud Native Starter example and run both the Authors microservice and the JUnit test on OpenLiberty in the development mode.

That post hasn’t the objective to be a blueprint or a ‘how to guide’ for writing JUnit tests,  JUnit test organization, test strategy and so on. The objective is to get technically started along one concrete microservice example from the Cloud Native Starter project.

The Authors microservice has one RESTful api endpoint called getAuthor. The endpoint provides one parameter for the Author name. The endpoint returns Author data in a JSON format.

Keep the end in mind: The gif shows a sample JUnit test execution for the Author microservice using OpenLiberty in the Visual Studio Code editor:

{% youtube LXVGyHgBibY %}

---

## Let's start with: What do we need and how do we realize the implementation?

* We need to ..
  * _invoke_ the REST endpoint of the Authors microservice with a REST Client.
  * _transform_ the JSON response of the REST endpoint to an Author data class
  * _handle_ different values to invoke the REST Endpoint parameter for the Author name to run tests with variations of the Author name.
  * _compare_ the actual response value with an expected value and document the result.

* And how to ..
  * setup a JUnit test for the development mode of the OpenLiberty server?
  * convert JSON Data from a String to an Author Java instance with JSON-B?
  * define a REST Client?
  * configure a parameterized JUnit test?
  * write the concrete parameterized JUnit test?
  * execute the JUnit test?
  * find the test results?

## What are the tools and frameworks?

* That are the Tools and frameworks of the sample project:
  * IDE: Visual Studio Code with the Java Development Extension
  * Server: Open Liberty
  * Frameworks: Eclipse MicroProfile
  * Java project organization: Apache Maven

## 1. How to setup a JUnit test for the development mode of the OpenLiberty server?

To setup and run JUnit tests with the OpenLiberty server in the development mode, we have to provide a test folder in the src folder of our Java project. The image below shows the folders of my sample project.

![Folder structure](https://dev-to-uploads.s3.amazonaws.com/i/pbvvvyg7ixdh9im0qmil.png)

## Content of the `com.ibm.authors` package for the Authors microservice
* `AuthorsApplication` class represents the JAX-RS RESTful web application.
* `Author` class represents the data structure we use for the Author.
* `GetAuthor` class represents the REST API Endpoint.
* `HealthEndpoint` class represents the support of readiness probes for Kubernetes.

## Content of the `authortests` package for the JUnit test
* `AuthorJsonbAdapter` class represents JSON-B adapter for a JSON-B mapping configuration.
* `AuthorTestClient` class represents the REST Client of the Authors microservice.
* `Test_GetAuthors` class represents the JUnit test which will be executed as the parameterized test run.

---

### 1.2 The `pom.xml` configuration for the JUnit and OpenLiberty

* Dependencies

The `junit-jupiter-api` and the `junit-jupiter-engine` are the basics for the Unit tests. With the `junit-jupiter-params` depencency we can define later a parameterized test.

```xml
<!-- JUnit Test --> 
<dependency> 
 <groupId>org.junit.jupiter</groupId> 
 <artifactId>junit-jupiter-api</artifactId> 
 <version>5.6.0</version> 
 <scope>test</scope> 
</dependency> 
<dependency> 
 <groupId>org.junit.jupiter</groupId> 
 <artifactId>junit-jupiter-engine</artifactId> 
 <version>5.6.0</version> <scope>test</scope> 
</dependency> 
<dependency> 
 <groupId>org.junit.jupiter</groupId> 
 <artifactId>junit-jupiter-params</artifactId> 
 <version>5.6.0</version> 
 <scope>test</scope> 
</dependency> 
<!-- JUnit Test -->
```

* Build plugins
  * JUnit
    * `maven-surefire-plugin`
    * `maven-failsafe-plugin`

```xml
<!-- JUNIT --> 
<plugin> 
 <artifactId>maven-surefire-plugin</artifactId> 
 <version>2.22.2</version> 
</plugin> 
<plugin> 
 <artifactId>maven-failsafe-plugin</artifactId> 
 <version>2.22.2</version> 
</plugin> 
<!-- JUNIT -->
```

* OpenLiberty
 * `liberty-maven-plugin`

```xml
<!-- Enable liberty-maven plugin --> 
<plugin> 
 <groupId>io.openliberty.tools</groupId> 
 <artifactId>liberty-maven-plugin</artifactId> 
 <version>3.1</version> 
 <!-- libertyMavenConfiguration --> 
 <configuration> 
  <serverName>authorsDevJUnitServer</serverName> 
  <configFile>liberty/server.xml</configFile> 
 </configuration> 
 <!-- libertyMavenConfiguration --> 
</plugin> 
<!-- Enable liberty-maven-plugin -->
```

---

## 2. How to convert JSON Data from a String to an Author Java instance with JSON-B?

The response of our endpoint `getauthor` is a text in a JSON format, but we want use that data in an instance of an Author class.

In JSON-B we define a `JsonbAdapter` which does the conversion from JSON to an `Author` class instance. Therefor we `@Override` the operations `adaptToJson` and `adaptFromJson`. The operation `adaptFromJson` defines how to create an Author object from a JsonObject.

```java
// Author data class 
import com.ibm.authors.Author; 
// JSON-binding 
import javax.json.bind.adapter.JsonbAdapter; 
import javax.json.JsonObject; 
import javax.json.Json; 

public class AuthorJsonbAdapter implements JsonbAdapter<Author, JsonObject> 
{ ... 
  @Override 
  public Author adaptFromJson(final JsonObject jsonObject) throws Exception { 
   final Author author = new Author()
   author.setBlog(jsonObject.getString("blog")); 
   author.setName(jsonObject.getString("name")); 
   author.setTwitter(jsonObject.getString("twitter")); 
   return author; 
  } 
}
```

In the following code of the Test_GetAuthors class you see how to utilize the `AuthorJsonbAdapter` to create a new JSON-B configuration. That JSON-B configuration is used to create a JSON-B object. The JSON-B object contains the implemented operation fromJson and knows how to create an instance of an `Author` class.

```java
final JsonbConfig config = new JsonbConfig().withAdapters(new AuthorJsonbAdapter()); 
final Jsonb jsonb = JsonbBuilder.create(config); 
final Author author_json = jsonb.fromJson(response, Author.class);
```

---

## 3. How to define a REST Client?

The following code shows the interface class `AuthorTestClient`. That class contains the REST Client interface definition for the REST Endpoint of the Authors microservice. With the usage of the MicroProfile annotation `@RegisterRestClient` a RESTful Client will be created, when the interface is used in the JUnit test.

The expected return value of getAuthors response type is defined as a String.

```java
import javax.ws.rs.Path; 
import javax.ws.rs.GET; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.QueryParam; 
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @Path("/getauthor") 
@RegisterRestClient 
public interface AuthorTestClient { 
  @GET 
  @Produces(MediaType.APPLICATION_JSON) 
  public String getAuthor(@QueryParam("name") String name); 
}
```

---

## 4. How to configure the parameterized JUnit test?

The class `Test_GetAuthors` implements the JUnit test in the operation `testGetAuthor`. The test is defined as a `ParameterizedTest` and can be repeated with given values from a `CsvSource`.

* `ParameterizedTest`

Here you see the annotation `@ParameterizedTest` and the configuration of name.
The name contains the count of the parameters, that test has two parameters and can be repeated.

```java
@ParameterizedTest(name = "{index} => name=''{0},{1}''")
```

The concrete test implementation itself happens in the operation `testGetAuthor`. The operation contains the names for the parameters which were defined before. These parameters we will use in the test implementation.

```java
public void testGetAuthor( final String authorName, final String expectedResult)
```
For more details visit the [JUnit documentation](https://junit.org/junit5/docs/5.0.1/api/org/junit/jupiter/params/ParameterizedTest.html).

* `CsvSource`

The annotation `@CsvSource` contains a comma separated list of values for the test execution. The values are in order to fit to parameters `nameAuthor` (sample value: Thomas) and `expectedResult` (sample value: Thomas Suedbroecker).

```java
@CsvSource({"Thomas,Thomas Suedbroecker", 
            "Niklas,Niklas Heidloff", 
            "Michael,Michael Heinrich" })
```

For more details visit the [JUnit documentation](https://junit.org/junit5/docs/5.0.3/api/org/junit/jupiter/params/provider/CsvSource.html)

---

## 5. How to write the concrete parameterized JUnit test?

---

### Step 1: Create a REST Client

To invoke our REST Endpoint `getauthor` of the Authors microservice we use the `RestClientBuilder` from MicroProfile to create our REST Client.

We use our defined MicroProfile RestClient Interface `AuthorTestClient.class` and the `RestClientBuilder` will create for us an object instance for the `AuthorTestClient`.

```java
final AuthorTestClient authorClient = RestClientBuilder
 .newBuilder() .baseUri(baseURI) 
 .build(AuthorTestClient.class);
```

---

### Step 2: Invoke the REST Client#

Now we invoke the REST Client and we use our test parameter nameAuthor as input.

```java
final String response = authorClient.getAuthor(nameAuthor);
```

---

### Step 3: Convert the response to a Author data object

Once more the usage of JSON-B.

```java
final JsonbConfig config = new JsonbConfig().withAdapters(new AuthorJsonbAdapter()); 
final Jsonb jsonb = JsonbBuilder.create(config); 
final Author author_json = jsonb.fromJson(response, Author.class);
```

---

### Step 4: Compare the actual value of response with the expected value from the test parameter

To compare the actual and expected value we use the assertEquals from JUnit.

```java
assertEquals(expectedResult, author_json.getName());
```

If a the values aren't equal, assertEquals throws a `AssertionFailedError` exception and document the error in target/surefire-reports/TEST-authortests.Test_GetAuthors.txt file.

Here is an sample output of the `TEST-authortests.Test_GetAuthors.txt` file:

```sh
org.opentest4j.AssertionFailedError: expected: <Michael Heinrich> but was: <Niklas Heidloff> at authortests.Test_GetAuthors.testGetAuthor(Test_GetAuthors.java:60)
```
For more details see in the [JUnit documentation](https://junit.org/junit4/javadoc/latest/org/junit/Assert.html)

![test results](https://dev-to-uploads.s3.amazonaws.com/i/w384rh08iu1g2kfcpxma.png)

---

## 6. How to execute the JUnit test?

With the usage of the `liberty-maven-plugin` we can start the OpenLiberty server in the development mode with following Maven command:

```sh
$ mvn liberty:dev
```

Then we just press return.

```sh
$ [INFO] Press the Enter key to run tests on demand.
```

## 7. How to find the test results?

The test results are stored in the `target/surefire-reports/*` folder.

{% youtube Y2NHyErZ5Ns %}

## Here are additional useful blog posts, videos or manuals

**MicroProfile RestClient**

* [Overview MicroProfile REST Client (Tomitribe)](https://www.tomitribe.com/blog/overview-of-microprofile-rest-client/)

**JUnit**

* [Setup Unit Tests in OpenLiberty](https://github.com/OpenLiberty/open-liberty/wiki/Unit-Tests)
* [JUnit User Guide dependencies](https://junit.org/junit5/docs/5.1.0-M1/user-guide/#dependency-diagram)
* [Using microprofile rest client for system testing (Adam-Bien)](http://www.adam-bien.com/roller/abien/entry/using_microprofile_rest_client_for)
* [Unit 5 tutorial Writing parameterized tests (Petri Kainulainen)](https://www.petrikainulainen.net/programming/testing/junit-5-tutorial-writing-parameterized-tests/)
* [Create effective tests or create excuses — testing the Java EE way (Sebastian Daschner)](https://www.youtube.com/watch?v=JPctzdfxeXo)
* [JUnit user-guide running tests is vscode](https://junit.org/junit5/docs/current/user-guide/#running-tests-ide-vscode)

**Jsonb**

* [What is JSON binding with JSON-B (RIECKPIL)](https://rieckpil.de/whatis-json-binding-json-b/)
* [3 ways to convert String to JSON object in Java?](https://www.java67.com/2016/10/3-ways-to-convert-string-to-json-object-in-java.html)

I hope this was useful for you and let’s see what’s next?

Greetings,

Thomas

PS:  My GitHub project with the source code is [here](https://github.com/thomassuedbroecker/local-dev-junit).
[Resource on www.suedbroecker.net](https://suedbroecker.net/2020/03/04/write-and-execute-a-junit-test-for-a-java-microservice-based-on-mircoprofile-and-run-both-in-the-openliberty-development-mode/)