Правильный способ использования и тестирования созданного картографа - PullRequest
0 голосов
/ 10 сентября 2018

Недавно мы столкнулись с некоторым конфликтом при разработке нашей системы. Мы обнаружили, что у нас есть 3 разных подхода к тестированию в нашей команде, и нам нужно решить, какой из них лучше, и проверить, нет ли ничего лучше этого.

Сначала давайте посмотрим правде в глаза:
- в системе есть 3 уровня данных (DTO, доменные объекты, таблицы)
- мы используем картографы, созданные с помощью mapstruct для отображения объектов каждого слоя на другой
- мы используем mockito
- мы проводим юнит-тестирование каждого из наших слоев

Теперь конфликт: давайте предположим, что мы хотим протестировать ExampleService, который использует ExampleModelMapper для сопоставления ExampleModel с ExampleModelDto и выполняет некоторую дополнительную бизнес-логику, которая требует тестирования. Мы можем проверить правильность возвращаемых данных тремя различными способами:

a) Мы можем вручную сравнить каждое поле возвращаемого объекта с ожидаемым результатом:

assertThat(returnedDto)
                .isNotNull()
                .hasFieldOrPropertyWithValue("id", expectedEntity.getId())
                .hasFieldOrPropertyWithValue("address", expectedEntity.getAddress())
                .hasFieldOrPropertyWithValue("orderId", expectedEntity.getOrderId())
                .hasFieldOrPropertyWithValue("creationTimestamp", expectedEntity.getCreationTimestamp())
                .hasFieldOrPropertyWithValue("price", expectedEntity.getPrice())
                .hasFieldOrPropertyWithValue("successCallbackUrl", expectedEntity.getSuccessCallbackUrl())
                .hasFieldOrPropertyWithValue("failureCallbackUrl", expectedEntity.getFailureCallbackUrl())

б) Мы можем использовать реальный маппер (как в обычной логике) для сравнения двух объектов:

assertThat(returnedDto).isEqualToComparingFieldByFieldRecursivly(mapper.mapToDto(expectedEntity)))

в) И, наконец, мы можем смоделировать маппер и его ответ:

final Entity entity = randomEntity();
final Dto dto = new Dto(entity.getId(), entity.getName(), entity.getOtherField());
when(mapper.mapToDto(entity)).thenReturn(dto);

Мы хотим, чтобы тесты были как можно лучше, сохраняя их эластичность и устойчивость к изменениям. Мы также хотим придерживаться принципа СУХОЙ.

Мы рады услышать любые советы, комментарии, плюсы и минусы каждого метода. Мы также открыты для просмотра любых других решений.

Привет.

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Есть два варианта, которые я бы посоветовал здесь.

Вариант 1 (отдельный пакет модульных тестов для сервиса и картографа) * ​​1003 * Если вы хотите выполнить модульное тестирование, тогда смоделируйте ваш маппер в сервисе (другие зависимости также OFC) и тестируйте только логику сервиса. Для картографа напишите отдельный набор тестов. Я создал пример кода здесь: https://github.com/jannis-baratheon/stackoverflow/tree/master/52255896-proper-way-of-using-and-testing-generated-mapper. Выдержки из примера: Класс обслуживания: public class AService { private final ARepository repository; private final EntityMapper mapper; public AService(ARepository repository, EntityMapper mapper) { this.repository = repository; this.mapper = mapper; } public ADto getResource(int id) { AnEntity entity = repository.getEntity(id); return mapper.toDto(entity); } } Mapper: import org.mapstruct.Mapper; @Mapper public interface EntityMapper { ADto toDto(AnEntity entity); } Проверка сервисной единицы: import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import org.junit.Before; import org.junit.Test; public class AServiceTest { private EntityMapper mapperMock; private ARepository repositoryMock; private AService sut; @Before public void setup() { repositoryMock = mock(ARepository.class); mapperMock = mock(EntityMapper.class); sut = new AService(repositoryMock, mapperMock); } @Test public void shouldReturnResource() { // given AnEntity mockEntity = mock(AnEntity.class); ADto mockDto = mock(ADto.class); when(repositoryMock.getEntity(42)) .thenReturn(mockEntity); when(mapperMock.toDto(mockEntity)) .thenReturn(mockDto); // when ADto resource = sut.getResource(42); // then assertThat(resource) .isSameAs(mockDto); } } Блок-тест Mapper: import static org.assertj.core.api.Assertions.assertThat; import org.junit.Before; import org.junit.Test; public class EntityMapperTest { private EntityMapperImpl sut; @Before public void setup() { sut = new EntityMapperImpl(); } @Test public void shouldMapEntityToDto() { // given AnEntity entity = new AnEntity(); entity.setId(42); // when ADto aDto = sut.toDto(entity); // then assertThat(aDto) .hasFieldOrPropertyWithValue("id", 42); } } Вариант 2 (интеграционные тесты для сервисных и картографических + модульных тестов)

Второй вариант - сделать интеграционный тест, в который вы добавляете реальный маппер в сервис. Я бы настоятельно рекомендовал не прилагать слишком много усилий для проверки логики сопоставления в интеграционных тестах. Это очень вероятно, чтобы стать грязным. Просто проведите тестирование сопоставлений и напишите отдельные тесты для картографа.

Краткое описание

Подведем итог:

  • модульные тесты для службы (с использованием макета) + модульные тесты для картографа
  • интеграционные тесты для сервиса (с реальным маппером) + модульные тесты для маппера

Обычно я выбираю вариант номер два, где я тестирую основные пути приложения с помощью MockMvc и пишу полные модульные тесты для меньших модулей.

0 голосов
/ 12 сентября 2018

Чтобы проверить ExampleService, я думаю, что это хорошая идея, чтобы смоделировать mapper и его ответ, отделив поведение от теста Mapper и MapperImpl test.

Но вам нужно протестировать экземпляр Mapper, который я предпочитаю проверять с помощью фиктивных данных, или вы также можете протестировать его с помощью прибора.

Чтобы протестировать бизнес-логику (правила отображения), введенную в Mapper, вы можете проверить класс MapperImpl.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...