简体   繁体   English

JUnit和Mockito的分支覆盖

[英]Branch coverage with JUnit and Mockito

I am writing a test case using JUnit API for a method. 我正在使用方法的JUnit API编写测试用例。 I've covered all the scenarios but the one that is giving me a hard time is in the if block. 我已经介绍了所有场景,但是让我很难受的场景是if块。 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. 当我将鼠标悬停在这条线上时, Cobertura针对每种情况声明50%50%,但我不确定如何获得此覆盖。

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: JUnit测试用例:

@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 start variables. 令我困惑的是我在嘲笑的参数date ,它确定了endstart变量的值。

if( date.getTimeInMillis() >= start.getTimeInMillis() && date.getTimeInMillis() <= end.getTimeInMillis() ) {} is the line that I want to cover. if( date.getTimeInMillis() >= start.getTimeInMillis() && date.getTimeInMillis() <= end.getTimeInMillis() ) {}是我要介绍的行。

Thanks 谢谢

Firstly, you never told your mocked calendar objects what to do when getTimeInMillis() is called. 首先,您从未告诉模拟的日历对象在调用getTimeInMillis()时该怎么做。 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. 您需要对date.getTimeInMillis()在期望范围内的一组日历对象以及date.getTimeInMillis()在期望范围之外的另一组日历对象执行此操作。

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. 要覆盖另一面,请复制上面的内容,但将您的calendartarget.getTimeInMillis()设置为返回诸如1000L荒谬内容,并更改断言以反映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() . 您可能还希望将测试用例分解为多个方法,这些方法的名称反映每个测试方法所检查的内容,例如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. 这样,您的测试变得更小,更容易理解和调试,您的测试运行会产生更清晰,内容更丰富的测试报告,并且一项测试中的失败不会掩盖其他测试中的失败。

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

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