Skip to content
Advertisement

How to test Service method with ModelMapper call

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).

Advertisement