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.
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 -->
- 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 -->
- 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 -->
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;
}
}
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);
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);
}
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}''")
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)
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" })
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);
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);
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);
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());
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)
For more details see in the JUnit documentation
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
Then we just press return.
$ [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.
Here are additional useful blog posts, videos or manuals
MicroProfile RestClient
JUnit
- Setup Unit Tests in OpenLiberty
- JUnit User Guide dependencies
- Using microprofile rest client for system testing (Adam-Bien)
- Unit 5 tutorial Writing parameterized tests (Petri Kainulainen)
- Create effective tests or create excuses — testing the Java EE way (Sebastian Daschner)
- JUnit user-guide running tests is vscode
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)