简体   繁体   中英

PowerMockito: can not mock Calendar.getInstance

How looks my code

@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);
}
}

But in every case, Calendar call real method .getInstance(). In previous cases, everything worked fine with BDDMockito, but now i have a problem

Assuming that your actual is the one posted in the original question, I think you are using PowerMock wrong.

Suppose that I have the following class which has a method like the one, hard coupling to Calendar which I need to mock its creation (via the Calendar#getInstance method).

public class SomeClass {

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

}

For this to work properly and be able to mock the instance creation via the static instance creator, your tests should look like this:

@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));
    }

}

Key points here are the following:

  1. @PrepareForTest( { SomeClass.class } ) contains the class that is under test (in our case SomeClass ).
  2. Calendar is statically mocked using PowerMock and a new real instance is returned (the one created in the setUp method).

You can go ahead and use this example which works correctly as a template to adjust your tests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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