Java Mockito when-return 对象创建
Java Mockito when-return on Object creation
我正在尝试测试计算年龄的 class。计算年龄的方法如下所示:
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.
然后我尝试在计算器中创建一个方法 class 到 return 当前日期,如下所示:
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);
}
}
但是我遇到了完全相同的问题。那么关于在触发年龄计算时如何 return 预定义的 localdate 对象的任何想法?
与其嘲笑,我建议使用 Joda 的 DateTimeUtils 来 "freeze" 时间。您还需要在应用程序代码中使用 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,请考虑描述的一些方法 here,特别是注入 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();
}
}
我总是使用自己的 TimeFactory
来检索我的应用程序中的当前日期。这样我就可以灵活地操作它(在 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.
您可以扩展此代码以修复时间。
我建议你用技巧来测试你的方法:
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);
}
我正在尝试测试计算年龄的 class。计算年龄的方法如下所示:
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.
然后我尝试在计算器中创建一个方法 class 到 return 当前日期,如下所示:
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);
}
}
但是我遇到了完全相同的问题。那么关于在触发年龄计算时如何 return 预定义的 localdate 对象的任何想法?
与其嘲笑,我建议使用 Joda 的 DateTimeUtils 来 "freeze" 时间。您还需要在应用程序代码中使用 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,请考虑描述的一些方法 here,特别是注入 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();
}
}
我总是使用自己的 TimeFactory
来检索我的应用程序中的当前日期。这样我就可以灵活地操作它(在 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.
您可以扩展此代码以修复时间。
我建议你用技巧来测试你的方法:
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);
}