Search code examples
javaspringspring-bootunit-testingjunit

Unit and Integration Test(with database) for a save method


I searched quite a bit on the internet and stackoverflow and was not able to find a simple explanation and distinction with an added example between a unit test and an integration test.

I read about unit and integration tests, and my understanding currently is that on the one hand for unit test we only test that the method either runs for starters or runs and returns the desired output correctly without interacting with other systems. My understanding is that Mocking of objects should be used over here.

On the other hand for integration tests we test a more complex situation like the running of a method in relationship with a database call or another service call. My understanding is that no mocking of objects should be used over here, and a real call to the database should be done. Is this so ?

I am using Java 11, Junit 5 and would like to test the Rest Controllers of a basic CRUD application with a MySQL db and JPA Repositories(Hibernate). I have created some unit tests , but am unable to create the integration test because of lack of understanding between them and how to leverage Junit to do that. I would like, if possible a clear example of unit and integration test for the below method with a clear explanation, using the current best practices in the business.

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/message")
@Slf4j
public class MessageController {

    private final MessageService messageService;

    @PostMapping("/save")
    public ResponseEntity<MessageDto> saveMessage(@RequestBody MessageDto messageDto) {
        messageService.saveMessage(messageService.dtoToEntity(messageDto));
        log.info("In saveMessage() , saving: " + messageDto);
        return ResponseEntity.ok().body(messageDto);
    }

and the service layer

@Service
@RequiredArgsConstructor
public class MessageService {
    
private final MessageRepository messageRepository;

    public Message saveMessage(Message message) {
        return messageRepository.save(message);
    }


    public Message dtoToEntity(MessageDto message) {
        return Message.builder()
                .title(message.getTitle())
                .name(message.getName())
                .mail(message.getMail())
                .message(message.getMessage())
                .id(message.getId())
                .build();
    }
}

Solution

  • Unit tests only check the Class Under Test (CUT). So, they check only a class. Normally, all dependencies must be mocked.

    If your code is under Solid Principles, the dependencies should be easy to mocked. If not, you must change you CUT to make it testable.

    Integrations tests check the CUT and their dependencies together. So, they check a class like the production workflow.

    You must start creating unit tests for your CUT and an integration test after that.