DEV Community

Cover image for Write and execute a JUnit test for a Java microservice based on MicroProfile and run both in the OpenLiberty development mode
Thomas Südbröcker
Thomas Südbröcker

Posted on

Write and execute a JUnit test for a Java microservice based on MicroProfile and run both in the OpenLiberty development mode

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:


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

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.

<!-- 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 -->
Enter fullscreen mode Exit fullscreen mode
  • Build plugins
    • JUnit
    • maven-surefire-plugin
    • maven-failsafe-plugin
<!-- 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 -->
Enter fullscreen mode Exit fullscreen mode
  • OpenLiberty
    • liberty-maven-plugin
<!-- 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 -->
Enter fullscreen mode Exit fullscreen mode

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.

// 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; 
  } 
}
Enter fullscreen mode Exit fullscreen mode

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.

final JsonbConfig config = new JsonbConfig().withAdapters(new AuthorJsonbAdapter()); 
final Jsonb jsonb = JsonbBuilder.create(config); 
final Author author_json = jsonb.fromJson(response, Author.class);
Enter fullscreen mode Exit fullscreen mode

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.

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); 
}
Enter fullscreen mode Exit fullscreen mode

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.

@ParameterizedTest(name = "{index} => name=''{0},{1}''")
Enter fullscreen mode Exit fullscreen mode

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.

public void testGetAuthor( final String authorName, final String expectedResult)
Enter fullscreen mode Exit fullscreen mode

For more details visit the JUnit documentation.

  • 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).

@CsvSource({"Thomas,Thomas Suedbroecker", 
            "Niklas,Niklas Heidloff", 
            "Michael,Michael Heinrich" })
Enter fullscreen mode Exit fullscreen mode

For more details visit the JUnit documentation


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.

final AuthorTestClient authorClient = RestClientBuilder
 .newBuilder() .baseUri(baseURI) 
 .build(AuthorTestClient.class);
Enter fullscreen mode Exit fullscreen mode

Step 2: Invoke the REST Client

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

final String response = authorClient.getAuthor(nameAuthor);
Enter fullscreen mode Exit fullscreen mode

Step 3: Convert the response to a Author data object

Once more the usage of JSON-B.

final JsonbConfig config = new JsonbConfig().withAdapters(new AuthorJsonbAdapter()); 
final Jsonb jsonb = JsonbBuilder.create(config); 
final Author author_json = jsonb.fromJson(response, Author.class);
Enter fullscreen mode Exit fullscreen mode

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.

assertEquals(expectedResult, author_json.getName());
Enter fullscreen mode Exit fullscreen mode

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:

org.opentest4j.AssertionFailedError: expected: <Michael Heinrich> but was: <Niklas Heidloff> at authortests.Test_GetAuthors.testGetAuthor(Test_GetAuthors.java:60)
Enter fullscreen mode Exit fullscreen mode

For more details see in the JUnit documentation

test results


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:

$ mvn liberty:dev
Enter fullscreen mode Exit fullscreen mode

Then we just press return.

$ [INFO] Press the Enter key to run tests on demand.
Enter fullscreen mode Exit fullscreen mode

7. How to find the test results?

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

Here are additional useful blog posts, videos or manuals

MicroProfile RestClient

JUnit

Jsonb

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.
Resource on www.suedbroecker.net

Top comments (0)