JUnit和Mockito的分支覆盖 [英] Branch coverage with JUnit and Mockito
问题描述
我正在使用JUnit
API编写一种方法的测试用例.我已经介绍了所有场景,但是让我很难受的场景是在if
块中.当我将鼠标悬停在这条线上时,Cobertura
会针对每种情况声明50%50%,但我不确定如何将其覆盖.
I am writing a test case using JUnit
API for a method. I've covered all the scenarios but the one that is giving me a hard time is in the if
block. When I hover over this line the Cobertura
states 50% 50% for each condition but I am not exactly sure how to get this covered.
被测方法:
protected boolean isDateWithinTimelineRange( Calendar date, ServiceContext ctx ) {
Calendar end = (Calendar)ctx.getParameter( ServiceConstants.TIMELINE_END );
Calendar start = (Calendar)ctx.getParameter( ServiceConstants.TIMELINE_BEGIN );
if( end != null && start != null ) {
if( date.getTimeInMillis() >= start.getTimeInMillis() && date.getTimeInMillis() <= end.getTimeInMillis() ) {
return true;
} else {
return false;
}
}
return true;
}
JUnit测试用例:
JUnit test case:
@Test
public void testIsDateWithinTimelineRange() throws Exception {
ServiceContext context = Mockito.mock(ServiceContext.class);
Calendar calender = Mockito.mock(Calendar.class);
Mockito.when(context.getParameter(Mockito.anyString())).thenReturn(calender);
TestBaseTimelineProvider provider = new TestBaseTimelineProvider();
boolean answer = provider.isDateWithinTimelineRange(calender, context);
assertNotNull(answer);
assertTrue(provider.isDateWithinTimelineRange(calender, context));
// Testing for NULL condition
context = Mockito.mock(ServiceContext.class);
calender = Mockito.mock(Calendar.class);
Mockito.when(context.getParameter(Mockito.anyString())).thenReturn(null);
provider = new TestBaseTimelineProvider();
answer = provider.isDateWithinTimelineRange(calender, context);
assertNotNull(answer);
assertTrue(provider.isDateWithinTimelineRange(calender, context));
// Start date set to null
context = Mockito.mock(ServiceContext.class);
calender = Mockito.mock(Calendar.class);
ServiceConstants constants = new ServiceConstants();
Mockito.when(context.getParameter(ServiceConstants.TIMELINE_END)).thenReturn(calender);
provider = new TestBaseTimelineProvider();
answer = provider.isDateWithinTimelineRange(calender, context);
assertNotNull(constants);
// End date set to null
context = Mockito.mock(ServiceContext.class);
calender = Mockito.mock(Calendar.class);
constants = new ServiceConstants();
Mockito.when(context.getParameter(ServiceConstants.TIMELINE_BEGIN)).thenReturn(calender);
provider = new TestBaseTimelineProvider();
answer = provider.isDateWithinTimelineRange(calender, context);
assertNotNull(constants);
}
让我困惑的是我正在嘲笑的参数date
,它确定了end
和start
变量的值.
What confuses me is the parameter date
that I am mocking and which determines the values for the end
and start
variables.
if( date.getTimeInMillis() >= start.getTimeInMillis() && date.getTimeInMillis() <= end.getTimeInMillis() ) {}
是我要介绍的行.
谢谢
推荐答案
首先,您从未告诉模拟日历对象在调用getTimeInMillis()
时该怎么做.您需要为每个日历条目添加以下内容:
Firstly, you never told your mocked calendar objects what to do when getTimeInMillis()
is called. You need to add the following for each calendar entry:
// Assume `long desiredlong` defined;
Mockito.when(calendar.getTimeInMillis()).thenReturn(desiredlong);
您需要对date.getTimeInMillis()在期望范围内的一组日历对象以及date.getTimeInMillis()在期望范围之外的另一组日历对象执行此操作.
You will need to do this for a set of calendar objects where the date.getTimeInMillis() is in the desired range, and another set where date.getTimeInMillis() is outside the desired range.
最终,涵盖该测试真实面的案例将采用以下形式:
Ultimately, a case that covers the true side of that test would take the form:
@Test
public void validDatesInRange() {
ServiceContext context = Mockito.mock(ServiceContext.class);
Calendar calenderstart = Mockito.mock(Calendar.class);
Mockito.when(calendarstart.getTimeInMillis()).thenReturn(1L);
Calendar calendertarget = Mockito.mock(Calendar.class);
Mockito.when(calendartarget.getTimeInMillis()).thenReturn(2L);
Calendar calenderend = Mockito.mock(Calendar.class);
Mockito.when(calendarend.getTimeInMillis()).thenReturn(3L);
Mockito.when(context.getParameter(ServiceConstants.TIMELINE_END)).thenReturn(calenderend);
Mockito.when(context.getParameter(ServiceConstants.TIMELINE_BEGIN)).thenReturn(calenderstart);
TestBaseTimelineProvider provider = new TestBaseTimelineProvider();
boolean answer = provider.isDateWithinTimelineRange(calendertarget, context);
assertNotNull(answer);
assertTrue(provider.isDateWithinTimelineRange(calendartarget, context));
}
第二,您实际上从未写过任何测试错误返回的东西.要覆盖另一面,请复制上面的内容,但将您的calendartarget.getTimeInMillis()
设置为返回诸如1000L
之类的荒谬内容,并更改您的断言以反映错误.
Secondly, you never actually wrote anything that tests for a false return. To cover the other side, copy the above but set your calendartarget.getTimeInMillis()
to return something ridiculous like 1000L
and change your assertions to reflect false.
您可能还希望将测试用例分解为多个方法,这些方法的名称反映每个测试方法要检查的内容,例如validDatesInRange()
,validDatesNotInRange()
,startDateIsNull()
,endDateIsNull()
,contextIsNull()
.这样一来,您的测试变得更小,更易于理解和调试,您的测试运行会产生更清晰,内容更丰富的测试报告,并且一项测试中的失败不会掩盖其他测试中的失败.
You may also wish to break your test cases into multiple methods whose names reflect what each individual test method checks for, like validDatesInRange()
, validDatesNotInRange()
, startDateIsNull()
, endDateIsNull()
, contextIsNull()
. By doing so, your tests become smaller and easier to understand and debug, your test runs produce cleaner and far more informative test reports, and a failure in one test will not mask failures in others.
这篇关于JUnit和Mockito的分支覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!