Branch coverage with JUnit and Mockito

谁说我不能喝 提交于 2019-12-25 07:27:24

问题


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.

Method under test:

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

What confuses me is the parameter date that I am mocking and which determines the values for the end and startvariables.

if( date.getTimeInMillis() >= start.getTimeInMillis() && date.getTimeInMillis() <= end.getTimeInMillis() ) {} is the line that I want to cover.

Thanks


回答1:


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

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

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.

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.



来源:https://stackoverflow.com/questions/37417797/branch-coverage-with-junit-and-mockito

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!