Reader small image

You're reading from  Mastering Spring Cloud

Product typeBook
Published inApr 2018
Reading LevelIntermediate
PublisherPackt
ISBN-139781788475433
Edition1st Edition
Languages
Right arrow
Author (1)
Piotr Mińkowski
Piotr Mińkowski
author image
Piotr Mińkowski

Piotr works as a Solution Architect at Red Hat. He has several years of experience in software architecture and development. During this time, he was working in large organizations, where he was responsible for IT transformation to the modern cloud-native development approach. He is interested in technologies related to programming, containerization, and microservices. He writes about it in his blog https://piotrminkowski.com.
Read more about Piotr Mińkowski

Right arrow

Chapter 13. Testing Java Microservices

While developing a new application, we should never forget about automated tests. These are especially important if we are thinking about microservices-based architecture. Testing microservices requires a different approach than the tests created for monolithic applications. As far as monoliths are concerned, the main focus is on unit testing and  integration tests, together with the database layer. In the case of microservices, the most important thing is to provide coverage for each of the communications at the finest possible granularity. Although each microservice is independently developed and released, a change in one of them can affect all of the others that are interacting with that service. The communication between them is realized through messages. Usually, these are messages that are sent via REST or AMQP protocols.

Topics we will cover in this chapter include the following:

  • Spring support for automated testing
  • Differences between a component...

Testing strategies


There are five different microservices testing strategies. The first three of them are the same as for monolithic applications:

  • Unit tests: With unit tests, we test the smallest pieces of code, for example, a single method or component, and mock every call of other methods and components. There are many popular frameworks that support unit tests in Java, such as JUnit, TestNG, and Mockito (for mocking). The main task of this type of testing is to confirm that the implementation meets requirements. Unit testing can be a powerful tool, especially when combined with test-driven development.
  • Integration tests: Using only unit testing doesn't guarantee that you will verify the behavior of the whole system. Integration tests take the modules and try to test them together. This approach gives you an opportunity to exercise communication paths within the subsystem. We are testing the interaction and communication between components based on their interfaces with external services...

Testing Spring Boot applications


As you might have read in the previous section, there are some different strategies and approaches to the tests in your application. I have briefly mentioned all of them, so now we may proceed to the practical aspects. Spring Boot provides a set of utilities that help in the implementation ofautomated tests. In order to enable these features in the project, you have to include thespring-boot-starter-teststarterto the dependencies. It imports not only thespring-testandspring-boot-testartifacts, but also some other useful test libraries, such as JUnit, Mockito, and AssertJ:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

Building the sample application

Before we start to work on automated tests, we need to prepare a sample business logic for testing purposes. We may use the same example system from the previous...

Unit tests


I have taken a lot of time to describe integration with MongoDB. However, testing persistence is one of the key points of automated tests, so it is very important to configure it properly. Now, we may proceed to the test's implementation. Spring Test provides support for the most typical testing scenarios, such as integration with other services through a REST client or integration with databases. We have a set of libraries available that allows us to easily mock interactions with external services, which is especially important for unit tests.

The following test class is a typical unit test implementation for a Spring Boot application. We have used the JUnit framework, which is the de facto standard for Java. The Mockito library is used here for replacing the real repository and controller with their stubs. Such an approach allows us to easily verify the correctness of every method implemented by the @Controller class. The test is performed in isolation from the external components...

Component tests


If you have provided the unit tests for all the key classes and interfaces in the application, you may proceed to the component tests. The main idea of component tests is to instantiate the full microservice in memory using in-memory test doubles and data stores. This allows us to skip the network connections. While for unit tests we were mocking all the database or HTTP clients, here we do not mock anything. We provide an in-memory data source for the database client and we simulate HTTP responses for the REST client.

Running tests with an in-memory database

One of the reasons I chose MongoDB is that it can be easily embedded with a Spring Boot application for testing purposes. To enable an embedded MongoDB for your project, include the following dependency in Maven pom.xml:

<dependency>
    <groupId>de.flapdoodle.embed</groupId>
    <artifactId>de.flapdoodle.embed.mongo</artifactId>
    <scope>test</scope>
</dependency>

Spring...

Integration tests


After creating unit and component tests, we have verified all the functionalities inside the microservices. However, we still need to test the interaction with other services, external data stores, and caches. In microservices-based architecture integration, tests are treated differently than they are in monolithic applications. Because all the relationships between internal modules have been tested through the component tests, we have tested only those modules that interact with external components.

Categorizing tests

It also makes sense to separate integration tests in the CI pipeline so that external outages don't block or break the build of the project. You should consider categorizing your tests by annotating them with @Category. You may create the interface especially for integration tests, for example, IntegrationTest:

public interface IntegrationTest  { }

Then, you can mark your test with that interface using the @Category annotation:

@Category(IntegrationTest.class...

Contract tests


There are some interesting tools especiallydedicated to contract testing. We will discuss this concept by looking at two of the most popular tools—Pact and Spring Cloud Contract.

Using Pact

As we have already mentioned, the main concept around contract tests is to define a contract between the consumer and provider, and then verify it independently for each service. Since the responsibility for creating and maintaining a contract lies mainly on the consumer side, this type of test is usually referred to as a consumer-driven test. The division into a consumer and provider side is clearly visible in Pact JVM. It provides two separated libraries, the first prefixed by pact-jvm-consumer and the second prefixed by pact-jvm-provider. Of course, the contract is created by the consumer in agreement with the provider, which has been illustrated in the following diagram:

Pact is, in fact, a collection of frameworks that provide support for consumer-driven contract testing. These implementations...

Performance testing


We still have one last type of automated test to discuss. It has already beenmentioned at the beginning of the chapter. I am, of course, talking about performance tests. There are some really interesting tools and frameworks that help you to create and run this kind of test. There is a large choice of instruments, especially if we are talking about HTTP API tests. I wouldn't like to discuss all of them, but I will talk about one framework that might be helpful. It's Gatling. Let's take a closer look at it.

Gatling

Gatling is an open source performance testing tool written in Scala. It allows you to develop the tests in an easily readable and writable domain-specific language (DSL). It stands out from the competition by generating comprehensive, graphical load reports illustrating all the metrics collected during a test case. There are plugins available for integrating Gatling with Gradle, Maven, and Jenkins.

Enabling Gatling

To enable the Gatling framework for a project,...

Summary


In this chapter, I have introduced some frameworks that can help you effectively test your REST-based applications written in Java. Each of these solutions has been assigned to a particular type of test. I focused on tests strictly related to microservices, such as contract and component tests. The main goal of this chapter was to compare the two most popular frameworks used for contract testing, namely Pact and Spring Cloud Contract. Despite appearances, there are some significant differences between them. I tried to show you the most important similarities and differences based on the same sample applications that we looked at in previous chapters.

Microservices are strictly related to automation. Remember that migration from monolith to microservices gives you an opportunity to refactor your code, and, moreover, to improve the quality and code coverage of your automated tests. Frameworkssuch as Mockito, Spring Test, Spring Cloud Contract, and Pact, when used together, give you...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Mastering Spring Cloud
Published in: Apr 2018Publisher: PacktISBN-13: 9781788475433
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
Piotr Mińkowski

Piotr works as a Solution Architect at Red Hat. He has several years of experience in software architecture and development. During this time, he was working in large organizations, where he was responsible for IT transformation to the modern cloud-native development approach. He is interested in technologies related to programming, containerization, and microservices. He writes about it in his blog https://piotrminkowski.com.
Read more about Piotr Mińkowski