I’m writing some Unit Tests for my Service class, specifically, an update method that does exactly that, update an Entity with the given data from a request.
The problem is, I’m using ModelMapper to map the request data to the entity and when the test goes through the mapping statement it doesn’t actually call the modelMapper but the mock …. which does nothing because it’s a mock.
How should I mock its behavior?
public EntityNode updateEntity(String code, EntityDTO request) { String message = "Entity with code: %s not found"; EntityNode entity = repository.findByCode(code) .orElseThrow(() -> new EntityNotFoundException(String.format(message, code))); modelMapper.map(request, entity); return repository.save(entity); }
I’ve thought about using an ArgumentCaptor but I’m not really sure if it suits my needs or if it’s really what I need to do what I want.
This is my unfinished test method. After writing all of this I think I should stub ModelMappers.map() somehow and also return the result of calling the ModelMapper stub map() method when calling repository.save(entity).
@Test void givenValidEntity_whenUpdateEntity_shouldUpdateProperties() { //given String code = "TEST"; Entity expected = new Entity(); expected.setName("Old"); EntityDTO request = new EntityDTO(); request.setName("New") given(repository.findByCode(code)).willReturn(expected); //when Entity updatedEntity = service.updateEntity(code, request); //then assertEquals(request.getName(), updatedEntity.getName()); }
Does this make any sense?
Thanks
Advertisement
Answer
What does the changing?
By looking at the current code it seems like the modelMapper
does the changing. This would mean that changing unit test should be in modelMapper
‘s own unit test.
What does the EntityNode updateEntity(String code, EntityDTO request)
do?
It fetches an entity from a repository, takes your entity, passes it through modelMapper
and saves the result via repository. So while testing this function you should test only that those things happen with correct arguments, not what the modelMapper
itself does.
If you want to test your function + modelMapper
then this is more of an integration test not a unit test.
Additional notes
Ideally modelMapper would not mutate anything. Instead it would take the two arguments and return the result as a new object. This way it would be more easily testable and mockable (you could avoid using argument verification while testing updateEntity
function).