简体   繁体   English

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

[英]How to check if-statement in method using Mockito and JUnit?

I have method that I should test. 我有应该测试的方法。 Code (of course some parts were cut): 代码(当然,某些部分被剪切):

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

Question: how to check if-statement in method getPossibleFilterData using Mockito and JUnit? 问题:如何使用Mockito和JUnit检查方法getPossibleFilterData if语句? I want pass equal dates to method then check that my if-statement works properly. 我想将相等的日期传递给方法,然后检查我的if语句是否正常工作。

If you really want a pure unit test not an integration test, you could rely on the annotation @Mock to mock your service FilterDataProvider and @InjectMocks to inject your mock into your instance of FilterDataController . 如果您真的希望单元测试而不是集成测试,则可以依靠注释@Mock来模拟服务FilterDataProvider并使用@InjectMocks来将模拟注入到FilterDataController实例中。

Then you could propose 3 tests: 然后,您可以提出3个测试:

  1. One test where the dates are corrects but different, 日期正确无误的一项测试,
  2. Another one where the dates are corrects but equal 日期正确但相等的另一个日期
  3. And the last one where the dates are incorrect which will thrown a ValueNotAllowedException that could be tested out of the box using @Test(expected = ValueNotAllowedException.class) . 最后一个日期不正确的对象将抛出ValueNotAllowedException ,可以使用@Test(expected = ValueNotAllowedException.class)对其进行开箱测试。

If you need to make sure that filterDataProvider.getPossibleCountries(startDate, newEndDate) has been called with the expected arguments you need to use verify . 如果需要确保已使用期望的参数调用filterDataProvider.getPossibleCountries(startDate, newEndDate) ,则需要使用verify

The code would then be something like that: 该代码将是这样的:

@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
    }
}

You will have to mock FilterDataProvider and then inject this into your test class using InjectMocks. 您将必须模拟FilterDataProvider ,然后使用InjectMocks将其注入到测试类中。

getPossibleFilterData will be the method under test, so choose any specific date (use Calendar.set(...) , then Calendar.getTime() ) and send this same date as both the startDate and endDate. getPossibleFilterData将是被测试的方法,因此请选择任何特定日期(使用Calendar.set(...) ,然后选择Calendar.getTime() ),并将相同的日期作为startDate和endDate发送。

Now after getPossibleFilterData is completed, you can verify whether filterDataProvider.getPossibleCountries was called with a end Date that is one millisecond more than the start date. 现在,在完成getPossibleFilterData之后,您可以验证是否以结束日期(比开始日期多一毫秒)调用filterDataProvider.getPossibleCountries This can be done through Calendar.getTimeInMillis() inside the mocked class's method, or by verifying with Mockito with a Date that is one millisecond more than the date that was originally specified. 这可以通过模拟类的方法内的Calendar.getTimeInMillis()来完成,也可以通过使用Mockito进行验证,该Date的日期比最初指定的日期大一毫秒。

Edit: Code example provided: 编辑:提供的代码示例:

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

I see two main approaches. 我看到两种主要方法。

  1. Using Mockito functionality: if you inject your controller with a mock FilterDataProvider (which is the standard approach, using for example MockitoJUnitRunner and @InjectMocks) , then you can use Mockito's "verity" option to make sure it got the correct endDate. 使用Mockito功能:如果为控制器注入模拟FilterDataProvider(这是标准方法,例如使用MockitoJUnitRunner和@InjectMocks),则可以使用Mockito的“ verity”选项来确保其具有正确的endDate。 See discussion: http://www.vogella.com/tutorials/Mockito/article.html#mockito_verify 参见讨论: http : //www.vogella.com/tutorials/Mockito/article.html#mockito_verify
  2. Obviously, there are other approaches that rely on logic rather than technicalities. 显然,还有其他方法依赖逻辑而不是技术。 For example: refactoring the "if" part to a separateMethod "correctEndDate", or populating your data so that a different list of coutries is returned based on the endDate. 例如:将“ if”部分重构为单独的方法“ correctEndDate”,或填充数据,以便根据endDate返回不同​​的coutries列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM