我正在使用Calendar对象来确定是否根据当前日/小时值增加系统的工作负载。鉴于此对象使用静态方法,我使用PowerMock使用以下注释模拟静态方法:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Calendar.class })
测试中的代码非常简单(虽然我的逻辑需要工作,但我知道):
public void determineDefaultMaximumScans() throws ParseException{
parseTime();
Calendar cal = Calendar.getInstance();
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
System.out.println(cal.get(Calendar.DAY_OF_WEEK));
if(dayOfWeek == (Calendar.SATURDAY) || dayOfWeek == (Calendar.SUNDAY)){
setDefaultMax(calculateNewDefaultMax(getDefaultMax()));
System.out.println("defaultMax increased by 20%");
} else {
if(currentTime.after(afterHoursBegin) && currentTime.before(afterHoursEnd)){
System.out.println("Not afterhours. Maintaining current maximum.");
setDefaultMax(defaultMax);
System.out.println("Current Maximum number of scans: " + getDefaultMax());
}
}
}
我的测试用例如下:
@SuppressWarnings("static-access")
@Test
public void testDetermineMaximumScans() throws ParseException{
PowerMock.mockStatic(Calendar.class);
String beginningTime = "18:00";
String endingTime = "05:00";
mockAfterHoursBegin = parser.parse(beginningTime);
mockAfterHoursEnd = parser.parse(endingTime);
mockCurrentTime = parser.parse(parser.format(new Date()));
EasyMock.expect(Calendar.getInstance()).andReturn(mockCalendar);
EasyMock.expect(mockCalendar.get(Calendar.DAY_OF_WEEK)).andReturn(6);
EasyMock.replay(mocks);
offHourMaximumCalculator.determineDefaultMaximumScans();
EasyMock.verify(mocks);
}
截至目前,我所有返回特定值的尝试都会导致以下断言错误。现在我模糊地理解为什么它会返回默认值,但我不明白为什么我不能强迫价值或如何绕过这个期望。对我来说,模拟一般来说仍然是一个令人沮丧的谜。我错过了什么?
java.lang.AssertionError:
Expectation failure on verify:
Calendar.get(7): expected: 1, actual: 0
答案 0 :(得分:1)
模拟很简单。但是想要模拟静态方法在复杂性之后是一个很大的运行。我一般不建议模仿像日历这样的东西。如果你做了奇怪而复杂的事情,只需封装一些你可以轻松测试和模拟的东西。
事实上,我们几乎从不使用Calendar.getInstance()
。它根据语言环境返回一些内容。但是您很少需要特定日历,即GregorianCalendar
。所以只需new GregorianCalendar
。
但无论如何,添加一个受保护的方法
protected Calendar newCalendar() {
return Calendar.getInstance(); // or new GregorianCalendar()
}
将需要2分钟,然后一个简单的部分模拟将完成这个伎俩。
最后,我也不建议使用Calendar
。 Java 8中的java.util.date
中有一个更好的API。
所有这些都说,这就是你应该怎么做的。 Calendar是一个系统类,因此您需要遵循一个真实的特定路径,该路径由here解释。
@RunWith(PowerMockRunner.class)
@PrepareForTest(Calendar.class)
public class MyTest {
@Test
public void testDetermineMaximumScans() throws ParseException {
PowerMock.mockStatic(Calendar.class);
Calendar calendar = mock(Calendar.class);
EasyMock.expect(Calendar.getInstance()).andReturn(calendar);
EasyMock.expect(calendar.get(Calendar.DAY_OF_WEEK)).andReturn(6);
// really important to replayAll to replay the static expectation
PowerMock.replayAll(calendar);
assertThat(Calendar.getInstance().get(Calendar.DAY_OF_WEEK)).isEqualTo(6);
// and verifyAll is you want to verify that the static call actually happened
PowerMock.verifyAll();
}
}