繁体   English   中英

Java Mockito何时返回对象创建

[英]Java Mockito when-return on Object creation

我正在尝试测试计算年龄的课程。 计算年龄的方法如下所示:

public static int getAge(LocalDate birthdate) {
    LocalDate today = new LocalDate();
    Period period = new Period(birthdate, today, PeriodType.yearMonthDay());
    return period.getYears();
}

因为我希望JUnit与时间无关,所以我希望today变量始终为2016年1月1日。为此,我尝试使用Mockito.when路线,但遇到了麻烦。

我首先有这个:

public class CalculatorTest {

    @Before
    public void setUp() throws Exception {
        LocalDate today = new LocalDate(2016,1,1);

        Mockito.when(new LocalDate()).thenReturn(today);
    }
}

但是到此我得到了这个错误:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.

因此,我尝试在Calculator类中创建一个方法以返回当前日期,如下所示:

public static LocalDate getCurrentDate() {
    return new LocalDate();
}

public static int getAge(LocalDate birthdate) {
    LocalDate today = getCurrentDate();
    Period period = new Period(birthdate, today, PeriodType.yearMonthDay());
    return period.getYears();
}

这样我就可以做到这一点:

public class CalculatorTest {

    @Before
    public void setUp() throws Exception {
        CalculatorTest mock = Mockito.mock(CalculatorTest.class);
        LocalDate today = new LocalDate(2016,1,1);

        Mockito.when(mock.getCurrentDate()).thenReturn(today);
    }
}

但是,我得到了完全相同的问题。 那么,关于何时触发年龄计算如何返回预定义的本地日期对象的任何想法?

我建议不要使用模拟,而是使用Joda的DateTimeUtils “冻结”时间。 您还需要在应用程序代码中使用org.joda.time.LocalDate而不是java.time.LocalDate

public class CalculatorTest {

    @Before
    public void setUp() throws Exception {
        DateTimeUtils.setCurrentMillisFixed(new LocalDate(2016,1,1).toDateTimeAtStartOfDay().getMillis());
    }

    @After
    public void tearDown() {
        DateTimeUtils.setCurrentMillisSystem();
    }
}

对于纯Java,请考虑此处介绍的一些方法,特别是注入Clock或使用PowerMock。

注入Clock与Joda示例非常相似。 您只需要维护自己的静态Clock 您的应用程序代码如下所示:

static Clock appClock = Clock.systemDefaultZone();

public static int getAge(LocalDate birthdate) { 
  LocalDate today = LocalDate.now(appClock);
  Period period = new Period(birthdate, today, PeriodType.yearMonthDay());
  return period.getYears(); 
}

测试会冻结这样的时间:

public class CalculatorTest {

    @Before
    public void setUp() {
       appClock = Clock.fixed(LocalDate(2016,1,1).toDateTimeAtStartOfDay(), ZoneId.systemDefault());
    }

    @After
    public void tearDown() {
       appClock = Clock.systemDefaultZone();
    }
}

我建议您欺骗以测试您的方法:

public static int getAge(LocalDate currDate, LocalDate birthdate) {
    Period period = new Period(birthdate, currDate, PeriodType.yearMonthDay());
    return period.getYears();
}

public static int getAge(LocalDate birthdate) {
    return getAge(new LocalDate (), birthdate);
}

我总是使用自己的TimeFactory来检索应用程序中的currentdate。 这样,我可以灵活地进行操作(在JUnit测试期间)。 这是TimeFactory的样子:

public final class TimeFactory {

    static int offsetAmount = 0;
    static TemporalUnit offsetUnit = ChronoUnit.MILLIS;

    public static LocalDateTime getLocalDateTimeNow() {
        return LocalDateTime.now().plus(offsetAmount, offsetUnit);
    }

    public static void reset() {
        offsetAmount = 0;
    }

    public static void travelToPast(int amount, TemporalUnit unit) {
        offsetAmount = amount * -1;
        offsetUnit = unit;
    }

    public static void travelToFuture(int amount, TemporalUnit unit) {
        offsetAmount = amount;
        offsetUnit = unit;
    }
}

使用此TimeFactory,我可以轻松地进行时间旅行:

// start test
TimeFactory.travelToPast(10, ChronoUnit.HOURS);
// continue tests
TimeFactory.reset();
// check that things have happend in the past.

您可以扩展此代码以固定时间。

暂无
暂无

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

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