Issue
I have a service:
@Service
@Transactional
@RequiredArgsConstructor
public class BookService {
private final BookRepository bookRepository;
public Book findOne(Long id) {
return bookRepository.findById(id).orElse(null);
}
public Book getOne(Long id) {
return bookRepository.findById(id)
.orElseThrow(() -> new BadRequestAlertException("entity-not-found", ("Entity with id: " + id + " not found!")));
}
public List<Book> getAll() {
return bookRepository.findAll();
}
public Book save(Book book) {
return bookRepository.save(book);
}
}
I have written Integration tests for both database (BookRepository) and controller layer (BookController which uses BookService). I can't find anywhere examples of integration tests for service layer. If I write unit tests properly, is there any use case for writting integration tests for it? As far as I can tell (it's not a rule, but common use cases):
- Controller - Integration tests
- Service - Unit tests
- Repository - Integration tests
Solution
OK, so here's how you can think of it ...
It makes zero sense to write unit tests for
repositories
, they are only ever covered by integration tests. The choice to use anin-memory DB
or a proper DB from a Docker container depends on the circumstances, but generally I'd go for a DB in a Docker container, since H2 (even with saypostgres
dialect) is not a complete copy of thePostgres
DB. Therefore, the tests might run, but the app will crash in production.For
controllers
, you might want to have a mix of unit and integration tests. Test the majority of controller stuff using theMockMvc
class. And the most critical scenarios are covered by integration tests to test the whole vertical ( 3 layered ) slice of functionality.Now we get to the
services
part. If your service has complicated business logic, which you want to validate, then it must be covered by unit tests, so that you can do a lot of checks is a small amount of time. Also, it makes sense to cover some of the most basic scenarios by integration tests. In specifically your case, the business logic inside the service layer is extremely simple, so I'd go for just the integration tests. If and when it gets more complicated, you can add also some unit tests, where you mock out the repository classes to have blazing fast test times and being able to make a lot of check without slowing down theCI
pipeline for everyone on the project.
In general, try to always follow the test pyramid pattern and use the best possible testing libraries provided by the Spring Boot ecosystem.
Answered By - Arthur Klezovich