I want to test my Spring Boot application's layers - service, data, controllers.
I know with Spring Boot we can test these with server involvement or without involvement (by creating a mock environment). So my question here is - what is the best practise to test these layers? Or if it depends on the specific layer which we want to test?
Unit testing is straightforward.. you stick to SRP principle, mock out all the collaborators and test in isolation.
When it comes to integration testing there is no clear answer and definite standard. It always depends on the project you are working on and even the specific feature.
After working with a few Spring Boot applications I am leaning towards splitting your IT suite into four parts/categories:
1) REST API Tests
So we test only the @Restontrollers
. You use @WebMvcTest(MyController.class)
or @WebFluxTest(MyController.class)
depending on why type of controller you use. Anything from the service layer down is mocked. You put as much emphasis on inputs params/request body as possible and test the hell out of every combination.
2) Repository Tests
Tests that verify the ORM layer only. You use @DataJpaTest
for this. Here you test every possible scenario for each repository method you have, without caring what invoked it etc.
3) Slice Tests
This is where you verify the interaction between your @Component
and @Service
beans. This is where the actual business logic of your app is tested. It is up to decide whether you send the data via REST or use a call to the top-most @Service
. I always stubbed the @Repository
layer though in this case.
4) End to End Tests
These work on a real Web Server:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
Nothing is mocked here.
Discussion
The key here is to decide how much each of these should be used, keeping in mind that slice testing is probably the most important.
The main emphasis should NOT be put on E2E tests for sure. They are sort of a comma at the end of a sentence. They are the slowest and require most set-up. Thus they are most error-prone, hard to maintain and hard to understand. Ideally, these should be kept to a bare minimum (most crucial cases covered only).
Also when running your IT suite they should be grouped in this order:
1) Controller Tests
2) Slice Tests
3) Repository Tests
4) E2E Tests
(from the fastest and requiring least environment interaction to the slowest).
Again, it is up to the team to decide which ones of these we want to use, in what order and with what frequency.
Additional Read: I have written an article about common integration testing mistakes which may complement information given above and help you out even further in your projects.