Как проверить оператор if в методе, используя Mockito и JUnit?

2

У меня есть метод, который я должен проверить. Код (конечно, некоторые части были разрезаны):

public class FilterDataController {

    public static final String DATE_FORMAT = "yyyy-MM-dd";

    @Autowired
    private FilterDataProvider filterDataProvider;

    @ApiOperation(value = "Get possible filter data",response = ResponseEntity.class)
    @ApiResponses(value = {
            @ApiResponse(...),
            @ApiResponse(...)})
    @RequestMapping(path = "...", method = RequestMethod.GET)
    public ResponseEntity<Object> getPossibleFilterData(
            @RequestParam(value = "startDate") @DateTimeFormat(pattern=DATE_FORMAT) final Date startDate,
            @RequestParam(value = "endDate") @DateTimeFormat(pattern=DATE_FORMAT) final Date endDate) {
        if (endDate.compareTo(startDate) == -1){
            throw new ValueNotAllowedException("End date should be after or equal start date");
        }
        else {
            Date newEndDate = endDate;
            if (startDate.equals(endDate)){
                newEndDate = new Date(endDate.getTime() + TimeUnit.DAYS.toMillis(1) - 1);
            }

            List<String> possibleCountries = Lists.newArrayList(filterDataProvider.getPossibleCountries(startDate, newEndDate));

            return new ResponseEntity<>(new FilterResponse(possibleCountries),HttpStatus.OK);
        }
    }   
}

Вопрос: как проверить if-statement в методе getPossibleFilterData с помощью Mockito и JUnit? Я хочу передать равные даты методу, а затем проверить, что мой if-statement работает правильно.

  • 1
    Как упоминалось во многих ответах ниже, ваши тесты не должны предполагать вашу реализацию: что если вы реорганизуете метод, чтобы он возвращал правильные значения, но вообще не использовал оператор if ? Вместо того чтобы предполагать это, передайте ошибочные значения и проходите тест только тогда, когда вы поймаете правильное исключение .
  • 0
    @JeffBowman спасибо за совет.
Теги:
unit-testing
junit
mockito

3 ответа

2
Лучший ответ

Если вы действительно хотите, чтобы чистый unit тест не был интеграционным тестом, вы можете положиться на аннотацию @Mock чтобы @Mock вашу службу FilterDataProvider и @InjectMocks чтобы @InjectMocks ваш макет в ваш экземпляр FilterDataController.

Затем вы можете предложить 3 теста:

  1. Один тест, где даты правильные, но разные,
  2. Другой, где даты правильные, но равные
  3. И последнее, где даты неверны, что вызовет ValueNotAllowedException которое может быть проверено из коробки с помощью @Test(expected = ValueNotAllowedException.class).

Если вам нужно убедиться, что filterDataProvider.getPossibleCountries(startDate, newEndDate) был вызван с ожидаемыми аргументами, вам нужно использовать verify.

Тогда код будет примерно таким:

@RunWith(MockitoJUnitRunner.class)
public class FilterDataControllerTest {
    @Mock
    FilterDataProvider filterDataProvider;
    @InjectMocks
    FilterDataController controller;

    @Test(expected = ValueNotAllowedException.class)
    public void testGetPossibleFilterDataIncorrectDates() {
        controller.getPossibleFilterData(new Date(1L), new Date(0L));
    }

    @Test
    public void testGetPossibleFilterDataCorrectDates() {
        // Make the mock returns a list of fake possibilities
        Mockito.when(
            filterDataProvider.getPossibleCountries(
                Mockito.anyObject(), Mockito.anyObject()
            )
        ).thenReturn(Arrays.asList("foo", "bar"));
        ResponseEntity<Object> response = controller.getPossibleFilterData(
            new Date(0L), new Date(1L)
        );
        Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
        // Make sure that 
        // filterDataProvider.getPossibleCountries(new Date(0L), new Date(1L))
        // has been called as expected
        Mockito.verify(filterDataProvider).getPossibleCountries(
            new Date(0L), new Date(1L)
        );
        // Test response.getBody() here
    }

    @Test
    public void testGetPossibleFilterDataEqualDates() {
        // Make the mock returns a list of fake possibilities
        Mockito.when(
            filterDataProvider.getPossibleCountries(
                Mockito.anyObject(), Mockito.anyObject()
            )
        ).thenReturn(Arrays.asList("foo", "bar"));
        // Call the controller with the same dates
        ResponseEntity<Object> response = controller.getPossibleFilterData(
            new Date(1L), new Date(1L)
        );
        Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
        Mockito.verify(filterDataProvider).getPossibleCountries(
            new Date(1L), new Date(TimeUnit.DAYS.toMillis(1))
        );
        // Test response.getBody() here
    }
}
  • 0
    спасибо за код Но как проверить, что filterDataProvider был вызван с правильными датами? Я хочу отправить getPossibleFilterData равные даты, а затем проверить, что filterDataProvider.getPossibleCountries(startDate, newEndDate) с исправленными датами.
1

Вам придется издеваться над FilterDataProvider а затем ввести это в свой тестовый класс с помощью InjectMocks.

getPossibleFilterData будет тестируемым методом, поэтому выберите любую конкретную дату (используйте Calendar.set(...), затем Calendar.getTime()) и отправьте ту же дату, что и startDate и endDate.

Теперь, после завершения getPossibleFilterData, вы можете проверить, был ли filterDataProvider.getPossibleCountries с конечной датой, которая на миллисекунду больше даты начала. Это можно сделать через Calendar.getTimeInMillis() внутри метода изделенного класса или путем проверки с помощью Mockito с датой, которая на миллисекунду больше, чем дата, которая была первоначально указана.

Изменение: пример кода:

public class FilterDataControllerTest {
    @Test
    public void testSameDate() {
        FilterDataProvider provider = Mockito.mock(FilterDataProvider.class);
        FilterDataController controller = new FilterDataController(provider);

        Date startDate = new GregorianCalendar(2016, Calendar.JANUARY, 11).getTime();
        Date endDate = new GregorianCalendar(2016, Calendar.JANUARY, 11).getTime();
        Date expectedEndDate = new Date(endDate.getTime() + TimeUnit.DAYS.toMillis(1) - 1);

        controller.getPossibleFilterData(startDate, endDate);

        Mockito.verify(provider).getPossibleCountries(Mockito.eq(startDate), Mockito.eq(expectedEndDate));
    }
}
  • 0
    «или проверяя с помощью Mockito» - можете ли вы объяснить, как это сделать? Мой оригинальный вопрос был об этом (как проверить, что endDate был изменен в случае endDate == startDate. Такой случай соответствует внутреннему оператору if).
  • 0
    @Woland Ive добавил пример кода для вас
Показать ещё 1 комментарий
0

Я вижу два основных подхода.

  1. Использование функциональности Mockito: если вы вводите свой контроллер с помощью fetch FilterDataProvider (который является стандартным подходом, используя, например, MockitoJUnitRunner и @InjectMocks), вы можете использовать параметр "истинность" Mockito, чтобы убедиться, что он получил правильный endDate. См. Обсуждение: http://www.vogella.com/tutorials/Mockito/article.html#mockito_verify
  2. Очевидно, существуют и другие подходы, основанные скорее на логике, чем на технических. Например: рефакторинг части "if" в отдельный метод "correctEndDate" или заполнение ваших данных, чтобы на основе endDate был возвращен другой список coutries.
  • 0
    спасибо за verify . Есть пример verify(test).testing(Matchers.eq(12)); , Но в моем случае я хочу проверить, что метод в моем методе был вызван с исправленными датами. Может быть, что-то вроде этого newEndDate = ...; verify(FilterDataController).getPossibleFilterData().getPossibleCountries(Matchers.eq(startDate, newEndDate));

Ещё вопросы

Сообщество Overcoder
Наверх
Меню