Unit test (Junit and Mockito) - Clean & maintainable test code requires zero unnecessary code

Asked

Viewed 315 times

1

I am writing the test of a findByID method():

public DoctorDTO getDoctorById(long id) throws DoctorNotFoundException {
        Optional<Doctor> doctorO = VerifyIfExists(id);

        return doctorMapper.toDTO(doctorO.get());
}

private Optional<Doctor> VerifyIfExists(long id) throws DoctorNotFoundException {
        Optional<Doctor> doctorO = doctorRepository.findById(id);
        if (doctorO.isEmpty()) {
            throw new DoctorNotFoundException(id);
        }
        return doctorO;
}

As you can see, I use a Mapper to return a Doctordto type.

On my test, using the mockite:


@Mock
DoctorRepository doctorRepository;

@Mock
DoctorMapper doctorMapper;

@InjectMocks
DoctorService doctorService;

@Test
void testGivenValidDoctorThenReturnThisDoctor() throws DoctorNotFoundException {

        DoctorDTO expectedDoctorDTO = createFakeDoctorDTO();
        Doctor expectedDoctor =  createFakeEntity();

        when(doctorRepository.findById(expectedDoctor.getId())).thenReturn(Optional.of(expectedDoctor));
        when(doctorMapper.toDTO(expectedDoctor)).thenReturn(expectedDoctorDTO);

        DoctorDTO doctorDTO = doctorService.getDoctorById(expectedDoctor.getId());

        assertEquals(expectedDoctorDTO, doctorDTO);

        assertEquals(expectedDoctorDTO.getCrm(), doctorDTO.getCrm());
        assertEquals(expectedDoctorDTO.getName(), doctorDTO.getName());

    }

It is returned to me that when(doctorMapper.toDTO(expectedDoctor)). thenReturn(expectedDoctorDTO);

is not used, but my method (doctorService.getDoctorByID) uses doctorMapper.toDTO. Would anyone know why the next message appears when I run the test ?

Unnecessary stubbings detected. Clean & maintainable test code requires zero unnecessary code. Following stubbings are unnecessary (click to navigate to relevant line of code): 1. -> at com.example.medicalrecordapi.services.DoctorServiceTest.testGivenValidDoctorThenReturnThisDoctor(DoctorServiceTest.java:61) Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.

I’m using Mockito the wrong way?

1 answer

1

Debugging the test, I noticed that two MOCKS of MAPPER were being created by Mockito, making this when(doctorMapper.toDTO(expectedDoctor)).thenReturn(expectedDoctorDTO);

was never executed, as it referenced a different Mock than it should.

I fixed changing there in my Mapper class the way it would be injected into the Service class.

Before Mapper was like this:

@Mapper
public interface DoctorMapper {

    DoctorMapper INSTANCE = Mappers.getMapper(DoctorMapper.class);

    @Mapping(target = "birthDate", source = "birthDate", dateFormat = "dd-MM-yyyy")

    Doctor toModel(DoctorDTO doctorDTO);

    DoctorDTO toDTO(Doctor doctor);
}

There in the service I was injecting dependency so:

private final DoctorMapper doctorMapper = DoctorMapper.INSTANCE;

I removed INSTANCE from Mapper and started injecting through the Lombok @Allargsconstructor constructor. It basically injects you with the dependencies and saves you from writing the builders.

After that the Mock was done correctly and the test passed as expected.

Mapper was like this:

@Mapper
public interface DoctorMapper {

    @Mapping(target = "birthDate", source = "birthDate", dateFormat = "dd-MM-yyyy")

    Doctor toModel(DoctorDTO doctorDTO);

    DoctorDTO toDTO(Doctor doctor);
}

And I injected the addiction like this:

@AllArgsConstructor(onConstructor = @__(@Autowired))
public class DoctorService {

    private final DoctorMapper doctorMapper;

    private final DoctorRepository doctorRepository;

...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.