如何使用Mockito和JUnit检查方法中的if语句?

时间:2016-10-11 10:35:59

标签: java unit-testing junit mockito

我有我应该测试的方法。代码(当然有些部分被删除):

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);
        }
    }   
}

问题:如何使用Mockito和JUnit检查方法getPossibleFilterData中的if语句?我希望将方法传递给方法,然后检查我的if语句是否正常工作。

3 个答案:

答案 0 :(得分:2)

如果你真的想要一个单元测试而不是集成测试,你可以依靠注释@Mock模拟你的服务FilterDataProvider@InjectMocks来将模拟注入您的FilterDataController实例。

然后你可以提出3个测试:

  1. 日期更正但不同的一项测试,
  2. 另一个日期更正但等于
  3. 的日期
  4. 最后一个日期不正确的日期会引发一个ValueNotAllowedException,可以使用@Test(expected = ValueNotAllowedException.class)开箱即用。
  5. 如果您需要确保使用预期参数调用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
        }
    }
    

答案 1 :(得分: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));
    }
}

答案 2 :(得分:0)

我看到两种主要方法。

  1. 使用Mockito功能:如果您使用模拟FilterDataProvider注入控制器(这是标准方法,例如使用MockitoJUnitRunner和@InjectMocks),那么您可以使用Mockito的“verity”选项来确保它获得正确的endDate。见讨论:http://www.vogella.com/tutorials/Mockito/article.html#mockito_verify
  2. 显然,还有其他方法依赖逻辑而非技术性。例如:将“if”部分重构为separateMethod“correctEndDate”,或者填充数据,以便根据endDate返回不同​​的coutries列表。