Ясность относительно выполнения модульного теста в Spring Boot Application - PullRequest
0 голосов
/ 07 февраля 2019

Я отказался от написания базовых модульных тестов с использованием JUnit для простых методов, которые добавляют два числа.Я могу проверить результат, используя семейство вызовов функций assert *.Теперь я хочу провести модульное тестирование контроллера Spring Boot.

Вот пример класса модульного тестирования -

public class MyJunitTest {
    private MockMvc mockMvc;
@Mock
private MyService service;

@InjectMocks
private MyController controller;

@Before
public void init() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void unitTestGetAssessmentDetails() {
    when(service.getTest(Someobject.class)).thenReturn(customObjectWithValues);
    Results results = controller.getCall(someRequestObject);
    assertEquals(results, someOtherObjectPrefilledWithValues);
}
}

Мой вопрос: если я знаю значения, установленные в customObjectWithValues, тогда я также задаю someOtherObjectPrefilledWithValues,тогда assertEquals всегда будет проходить тест, верно?По сути, это тестирование, если 1 == 1 вид теста.Так какой смысл делать эти юнит-тесты?Я знаю, что сервисный объект не должен подключаться к реальной БД, и, следовательно, мы его высмеиваем.Так какой смысл делать эти тесты?Мне не хватает более широкой картины о том, как просматривать юнит-тесты?

PS - Пожалуйста, не стесняйтесь удалять этот вопрос, если он нарушает правила этого форума.

Ответы [ 3 ]

0 голосов
/ 07 февраля 2019

Ваш тест подтверждает, что getCall возвращает ожидаемые результаты;это тест черного ящика.Поскольку вы пишете модульный тест, этого достаточно, чтобы «притвориться», что он выполняет модульный тест.Этот метод распространен в фирмах, которые связывают качество кода с охватом кода модульного теста.

Лучшим методом является определение шагов, которые будут выполнены классом контроллера, и проверка того, что каждый из них был выполнен (возможно, в правильномпорядок).

Я буду считать, что MyController.getCall выглядит примерно так:

@Autowired
private MyService myService;

public BlammyReturnValueType getCall(final BlammyRequestType request)
{
    final BlammyReturnValueType returnValue;

    returnValue = myService.someServiceMethod(request);

    return returnValue;
}

В этом случае я бы добавил следующее к тестовому методу unitTestGetAssessmentDetails:

... The current stuff including the assert.

Mockito.verify(service, times(1)).someServiceMethod(customObjectWithValues);

Это подтвердит, что метод обслуживания был вызван ровно один раз, что правильно в этом примере.

0 голосов
/ 07 февраля 2019

Хорошо, юнит-тестирование - это больше тестирование логики, написанной в вашей функции / контроллере / сервисе.Теперь ваша функция может быть очень простой или очень сложной.Например, ваша функция может принимать и UserId в запросе, подключаться к базе данных, получать данные и возвращать их, и, поскольку вы проверяете соединение с базой данных, вы можете почувствовать, что, если вы передаете макетируемый объект в качестве ответа базы данных, вы, очевидно,получить тот же ответ, так какой смысл тестирования.В этом случае может показаться правильным вообще не проверять.Но позвольте мне привести еще один пример, скажем, у вас есть очень сложная функция, которая берет некоторый UserId, получает данные о банковской истории пользователей за весь год, накапливает их и вычисляет сумму, заработанную пользователем за этот год.Теперь подумайте, насколько сложна эта функция.Теперь, так как вы смоделировали соединение с БД, вы передадите некоторые данные, и внутри будет выполняться много вычислений, которые дают пользователю заработанную сумму в виде Процентов на сохранение.Теперь, для определенных поддельных данных, вы знаете, что ответ должен прийти в виде некоторой X-суммы.Теперь, со временем, кто-то допустил ошибку (возможно, вычел что-то, что нужно было добавить).Теперь, когда вы запускаете тест.Этот тест не пройден, и вы знаете, что с логикой что-то не так.В данном случае вы не ожидаете, что выходные данные будут равны вашим смоделированным данным, по этим данным были проведены некоторые вычисления, поэтому для проверки правильности логики функции после каждого изменения необходимо написать модульный тест для проверки.Теперь, если вы видите здесь, вы не тестируете 1 == 1, а что-то другое.Вот почему люди пишут модульные тесты, чтобы проверить свою логику внутри блока кода.

Надеюсь, это поможет.

0 голосов
/ 07 февраля 2019

Обычно у нас есть 3 уровня: Контроллер, Сервис, Репозиторий (если хотите, DAO).Я обычно не тестирую контроллеры, потому что я не помещаю в них никакой логики, я просто определяю конечную точку и вызываю сервис.Сервис - это то, что я тщательно тестирую, чтобы вы добавили макеты в ваш сервис.Тогда вы будете издеваться над своим репозиторием, чтобы он не пытался подключиться к базе данных.

@InjectMocks
private MyService service;

@Mock
private MyRepository myrepo

@Test
public void unitTestGetAssessmentDetails() {
    when(myrepo.find(someInt)).thenReturn(customObjectWithValues);
    Results results = service.serviceMethod(someRequestObject);
    assertEquals(results, someOtherObjectPrefilledWithValues);
}

Поскольку предполагается, что контроллеры не имеют логики, им не требуется модульный тест, потому что, как вы правильно сказали, это тест 1 == 1.Но они будут проверены интеграционными тестами

...