我有一个应该测试的方法。代码(当然有些部分被删减了):
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语句是否正常工作。
如果您真的想要一个纯的单元测试而不是集成测试,您可以依靠注释@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
,然后使用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));
}
}
我看到两种主要的方法。
- 使用Mockito功能:如果你用模拟FilterDataProvider注入你的控制器(这是标准的方法,例如使用MockitoJUnitRunner和@InjectMocks),那么你可以使用Mockito的"verity"选项来确保它得到正确的endDate。见讨论:http://www.vogella.com/tutorials/Mockito/article.html#mockito_verify
- 显然,还有其他依赖于逻辑而不是技术的方法。例如:将"if"部分重构为一个separateMethod方法"correctEndDate",或者填充您的数据,以便根据endDate返回不同的国家列表。