Junit 操纵模拟日历对象以返回特定日期

Junit 操纵模拟日历对象以返回特定日期,junit,powermock,easymock,Junit,Powermock,Easymock,我正在使用Calendar对象来确定是否根据当前的日/小时值增加系统的工作负载。鉴于此对象使用静态方法,我将使用PowerMock使用以下注释模拟静态方法: @RunWith(PowerMockRunner.class) @PrepareForTest({ Calendar.class }) 虽然我的逻辑需要工作,但测试的代码非常简单,我知道: public void determineDefaultMaximumScans() throws ParseException{ parseTi

我正在使用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

mock相当简单。但是想要模拟静态方法是一项追求复杂性的艰巨任务。我一般不建议模仿日历之类的东西。如果你用它做了一些奇怪和复杂的事情,只需封装在一些你可以轻松测试和模拟的东西中

事实上,我们几乎从不使用Calendar.getInstance。它根据区域设置返回一些内容。但很少有人不想要一个特定的日历,即格里高利安日历。那就做新的格雷戈里安·卡伦达吧

但是无论如何,添加一个受保护的方法

protected Calendar newCalendar() {
    return Calendar.getInstance(); // or new GregorianCalendar()
}  
将需要2分钟,然后一个简单的局部模拟将完成此任务

最后,我也不建议使用日历。java 8中的java.util.date中有一个更好的API

所有这些都表明,以下是你应该怎么做。Calendar是一个系统类,所以您需要遵循下面解释的实际特定路径

仅供参考:Calendar是一个非常古老的类,现在是遗留类,几年前被ZonedDateTime等java.time类取代。
@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();
  }

}