TDD with Spring Boot Rest Application

Tharanga Rajapaksha
5 min readMar 27, 2021

--

CHAPTER 1 : SPRING BOOT TESTING

Overall Idea about Testing.

Testing in large systems.

100% coverage doesn’t work in production because you can test even getter and setter method and it will increase the coverage but even business logic to be verified.

Too low unit testing is not good at all. But too high testing will make modules slow.

TDD approach for Spring boot rest applicaiton

What is module.

A module encapsulate it’s data (Access only via API).

A module has cleary defined collaborators and APIs.

Has (almost) all layers ( Vertical slicing).

Very much like a microservice candidate.

Mostly likely a Bounded Context ( Words have their own definitions/classes.)

Test your modules.

as black boxes.

all flows and corners cases in milliseconds (no I/O).

add crucial-paths — that bring money with I/O.

Implement whole I/O part in memory for unit testing.

For integration testing actual database can be used.

TDD for Spring boot module/ micro service developments.

https://www.youtube.com/watch?v=s9vt6UJiHg4&t=1370s

There are two ways to do .

  1. Top down approach

Start from Integration tests and correct failure scenarios until all features are completed.

2. Bottom up approach.

Start from bottom components you have to write success unit test cases first and go until the integration tests completes.

Suppose above diagram shows beans of our microservice.

Green colored are the easiest to write unit testings due to there is no dependencies.

Yellow colored beans should use mocks for it’s dependencies.

If your system has log of mocks then it is better to go to integration testings instead of unit testings. Because mocks may not represent actual behaviors of the beans.

Blue colored beans has dependencies for external resources like database or exteranal microservices. In spring boot we call RestTemplate or web clients.

Mock Rest clients.

There is a way to mock them as well using MockRestServiceServer. It will give Intended output fro defined input. OkHTTP’s MockWebServer is this kind of Mock Service.

Example ( Not tested by myself).

Mock Data sources.

We have to use H2 like database to mock for integration testings for data sources. Some time there will be compatibility issues.

Testcontainers

It manages the life cycle in a docker container. This will start , execute our test cases and automatically shutdown.

Spring boot support it’s own test containers.

Ex :

@SpringBootTest anotation

@SpringBootTest anotation will enable the Springboot test facilites for testing.

There is another anotation called @ApplicationContextRunner which can be used to run test cases with customized configurations.

Context Cashing.

Spring boot has enabled context Cashing to reduce the cost . Following annotation will be used for it.

Sliced Tests

Sliced Tests menas instead of using full context of spring boot we can do the testings for horizontal slices of the project. It will layered approach and we can any layer of spring boot for specific test casses instead of using @SpringBootTest for full context.

You can see these anotations are used to focus on specific backend layers like database, webmvc, RestClientTest etc. Using above anotation we can just focus on specific slices.

Ex : How to use @WebMvcTest for slicked tests.

If we want to do the WebMvcTest then we have to mock repositories.

We can reduce above configurations by @MocBean anotation or @SpyBean anotation. SpyBean will keep existinb bean and will keep spying on it.

Ex :

Once we mock any bean it will replace the beans already available in the context already.

Evaluation of Junit5

Since SpringBoot 2.2 it has switched to junit 5. But junit 5 a module called vintage Engine and it will allow to run junit4 test cases on top of junit 5. So migration is easier.

CHAPTER 2 : JUNIT 5 WITH SPRING BOOT

I was wondering what are the must do test types and and how to distinguished them when we are in spring boot Rest application development.

JUnit 5 has a very interesting architecture. First of all, the project is split into three sub-projects: Jupiter, Vintage, and Platform. They communicate via published APIs, which allows tools and libraries to inject customized behavior. Then, each sub-project is split into several artifacts to separate concerns and guarantee maintainability. In this post we’ll explore the architecture itself as well as the reasons behind it.

With the concerns sorted out, “JUnit the tool” (which we use to write tests) and “JUnit the platform” (which tools use to run our tests) can be clearly separated. To drive the point home, the JUnit team decided to split JUnit 5 into three sub-projects:

“JUnit the tool” and “JUnit the platform” are clearly separated

  • JUnit Jupiter: The API against which we write tests (addresses concern 1.) and the engine that understands it (2a.).
  • JUnit Vintage: Implements an engine that allows to run tests written in JUnit 3 and 4 with JUnit 5 (2a.).
  • JUnit Platform: Contains the engine API (2c.) and provides a uniform API to tools, so they can run tests (2b.).

Reffernce : https://nipafx.dev/junit-5-architecture-jupiter

TDD Approach (From Controller to Service ).

In TDD first we can complete the controller level test cases with mock services to show expected outputs. Then developer to go deep by replacing real components and services instead of mock beans.

CHAPTER 3 : TEST DRIVEN DEVELOPMENT

--

--