Вопрос по unit-testing, junit, java, mockito – Как проверить оператор 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-оператор в методеgetPossibleFilterData используя Mockito и JUnit? Я хочу передать равные даты методу, а затем проверить, что мой оператор if работает правильно.

Как упоминалось во многих ответах ниже, ваши тесты не должны предполагать вашу реализацию: что если вы реорганизуете метод, чтобы он возвращал правильные значения, но не использовалif Скажите вообще? Вместо того, чтобы предполагать это,передать ошибочные значения а такжепройти тест только тогда, когда вы поймали правильное исключение. Jeff Bowman
@JeffBowman спасибо за совет. Woland

Ваш Ответ

3   ответа
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));
    }
}
Ваш код требует написать конструктор дляFilterDataController , но в моей ситуации это нелепо. Но спасибо за такой подход. Я запомню это. +1 Woland
@Woland Ive добавил пример кода для вас mdewit
«или проверяя с помощью Mockito» - можете ли вы объяснить, как это сделать? Мой оригинальный вопрос был об этом (как это проверитьendDate был изменен в случае endDate == startDate. Такой случай соответствует внутреннему if-утверждению). Woland
2

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

Тогда вы можете предложить 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
    }
}
спасибо за код Но как это проверитьfilterDataProvider был назван с правильными датами? Я хочу отправитьgetPossibleFilterData равные даты, а затем убедитесь, чтоfilterDataProvider.getPossibleCountries(startDate, newEndDate) звонил с исправленными датами. Woland
0

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

Похожие вопросы