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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39975396/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 04:49:11  来源:igfitidea点击:

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

javaunit-testingjunitmockito

提问by Woland

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 getPossibleFilterDatausing Mockito and JUnit? I want pass equal dates to method then check that my if-statement works properly.

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

采纳答案by Nicolas Filotto

If you really want a pureunit test not an integration test, you could rely on the annotation @Mockto mock your service FilterDataProviderand @InjectMocksto 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 ValueNotAllowedExceptionthat could be tested out of the box using @Test(expected = ValueNotAllowedException.class).
  1. 一项日期正确但不同的测试,
  2. 另一个日期正确但相等的
  3. 最后一个日期不正确的将抛出一个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
    }
}

回答by mdewit

You will have to mock FilterDataProviderand then inject this into your test class using InjectMocks.

您必须模拟FilterDataProvider,然后使用 InjectMocks 将其注入到您的测试类中。

getPossibleFilterDatawill 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(...), then Calendar.getTime())并发送与 startDate 和 endDate 相同的日期。

Now after getPossibleFilterDatais completed, you can verify whether filterDataProvider.getPossibleCountrieswas called with a end Date that is one millisecond more than the start date. 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.

现在getPossibleFilterData完成后,您可以验证是否filterDataProvider.getPossibleCountries以比开始日期多一毫秒的结束日期调用。这可以通过Calendar.getTimeInMillis()模拟类的方法内部来完成,或者通过使用比最初指定的日期多一毫秒的日期来验证 Mockito。

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

回答by Pelit Mamani

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