JUnit和Mockito的分支覆盖 [英] Branch coverage with JUnit and Mockito

查看:779
本文介绍了JUnit和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,它确定了endstart变量的值.

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() ) {}是我要介绍的行.

谢谢

推荐答案

首先,您从未告诉模拟日历对象在调用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆