简体   繁体   中英

Mocking constructor and static method from same class with Mockito and Powermock

I'm writing and application that is interfacing with a third party Java SDK. I'm currently using Mockito and PowerMock to write unit tests. I'm running into a problem mocking the classes provided by the sdk. The dummy class looks something like this:

class A{
    public static A getInstance() {
     ...
    }

    public A(){
     ...
    }
}

I'm trying to mock class B, which calls both the constructor of A, and the static method in A.

class B{
    public String doSomething(){
A test1 = A.getInstance();
A test2 = new A();

...

}
}

I need to be able to mock both the test1 and test2 objects within B's method, so I've tried writing the test as follows:

@RunWith( PowerMockRunner.class )
@PrepareForTest( B.class )

public class BTest{

    @PrepareForTest( A.class )
    @Test
    public void testdoSomething() {

        A mockedTest1 = Mockito.mock(A.class);
        A mockedTest2 = Mockito.mock(A.class);

        PowerMockito.whenNew(A.class).withAnyArguments().thenReturn(mockedTest2)
        PowerMockito.mockStatic( A.class )
        PowerMockito.when( A.getInstance()).thenAnswer(mockedTest1)


        B b = new B();
        b.doSomething();

    }

While the static method is being mocked, the constructor is not. However if I do not attempt to mock the constructor (ie remove the PrepareForTest annotation and change the code as follows:)

@RunWith( PowerMockRunner.class )
@PrepareForTest( B.class )

public class BTest{

    @Test
    public void testdoSomething() {

        A mockedTest1 = Mockito.mock(A.class);
        A mockedTest2 = Mockito.mock(A.class);

        PowerMockito.whenNew(A.class).withAnyArguments().thenReturn(mockedTest2)


        B b = new B();
        b.doSomething();

    }  

I can get the constructor to be mocked correctly. Is there something with Powermock that prevents mocking both constructors and static methods at the same time? Or is there something I'm missing?

Thanks.

You're pretty close yourself, but you have to consider a few things in order to make all pieces fit the puzzle:

1) Powermock documentation for mocking constructors

  1. Use the @PrepareForTest( ClassThatCreatesTheNewInstance.class ) annotation at the class-level of the test case.

2) Powermock documentation for mocking static methods

  1. Use the @PrepareForTest( ClassThatContainsStaticMethod.class ) annotation at the class-level of the test case

So far so good, we know we need to prepare for test both A.class (static method) & B.class (constructor), which you did, however you used @PrepareForTest both at class level as well as at test method level.

3) Powermock javadoc for @PrepareForTest

This annotation can be placed at both test classes and individual test methods. If placed on a class all test methods in this test class will be handled by PowerMock (to allow for testability). To override this behavior for a single method just place a @PrepareForTest annotation on the specific test method. This is useful in situations where for example you'd like to modify class X in test method A but in test method B you want X to be left intact .

In conclusion, either use @PrepareForTest({A.class, B.class}) at class level, or method level and everything should be fine.

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