PowerMockito:无法模拟 Calendar.getInstance

PowerMockito: can not mock Calendar.getInstance

我的代码看起来如何

@RunWith(PowerMockRunner.class)
@PrepareForTest({Calendar.class})
public class TestSomething {

  @Test
  public void mockCalendar() {
     Calendar calendar = Calendar.getInstance();
     PowerMockito.mockStatic(Calendar.class);
     //a few attempts here
     PowerMockito.when(Calendar.getInstance()).thenReturn(calendar);
     // or
     BDDMockito.when(Calendar.getInstance()).thenReturn(calendar);
     //or 
     Mockito.when(Calendar.getInstance()).thenReturn(calendar);
     //or
     BDDMockito.given(Calendar.getInstance()).willReturn(calendar);
}
}

但在任何情况下,Calendar 都会调用真正的方法 .getInstance()。 在以前的案例中,BDDMockito 一切正常,但现在我遇到了问题

假设您的实际是原问题中发布的那个,我认为您使用 PowerMock 错误。

假设我有以下 class,它有一个类似的方法,硬耦合到 Calendar,我需要模拟它的创建(通过 Calendar#getInstance 方法)。

public class SomeClass {

    public Calendar createInstance() {
        return Calendar.getInstance();
    }

}

为了使其正常工作并能够通过静态实例创建器模拟实例创建,您的测试应如下所示:

@RunWith(PowerMockRunner.class)
@PrepareForTest( { SomeClass.class } )
public class SomeClassTest {

    private static final int YEAR  = 2020;
    private static final int MONTH = Calendar.JANUARY;
    private static final int DAY   = 1;

    private SomeClass someClass;

    @Before
    public void setUp() throws Exception {
        Calendar instance = Calendar.getInstance();
        instance.set(YEAR, MONTH, DAY);
        PowerMockito.mockStatic(Calendar.class);
        PowerMockito.when(Calendar.getInstance()).thenReturn(instance);
        someClass = new SomeClass();
    }

    @Test
    public void testDoSomething() {
        Calendar mocked = someClass.createInstance();
        assertNotNull(mocked);
        assertEquals(YEAR, mocked.get(Calendar.YEAR));
        assertEquals(MONTH, mocked.get(Calendar.MONTH));
        assertEquals(1, mocked.get(Calendar.DAY_OF_WEEK_IN_MONTH));
    }

}

这里的要点如下:

  1. @PrepareForTest( { SomeClass.class } ) 包含正在测试的 class(在我们的例子中是 SomeClass)。
  2. Calendar 使用 PowerMock 进行静态模拟,并返回一个新的真实实例(在 setUp 方法中创建的实例)。

您可以继续使用这个可以正常工作的示例作为模板来调整您的测试。