使用Mockito和Powermock从同一类中模拟构造函数和静态方法

时间:2016-07-20 15:19:12

标签: java unit-testing mockito powermock powermockito

我正在编写与第三方Java SDK连接的应用程序。我目前正在使用Mockito和PowerMock编写单元测试。我遇到了一个模拟sdk提供的类的问题。虚拟类看起来像这样:

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

    public A(){
     ...
    }
}

我试图模拟B类,它既调用A的构造函数,又调用A中的静态方法。

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

...

}
}

我需要能够在B&B方法中模拟test1和test2对象,所以我尝试按如下方式编写测试:

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

    }

在静态方法被模拟时,构造函数不是。但是,如果我不尝试模拟构造函数(即删除PrepareForTest注释并按如下方式更改代码:)

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

    }  

我可以正确地模拟构造函数。有没有Powermock可以防止同时模拟构造函数和静态方法?或者我有什么遗失的东西?

感谢。

1 个答案:

答案 0 :(得分:0)

你自己很亲密,但你必须考虑一些事情,以使所有部分适合这个难题:

1)Powermock documentation for mocking constructors

  
      
  1. 在测试用例的类级别使用@PrepareForTest( ClassThatCreatesTheNewInstance.class )注释。
  2.   

2)Powermock documentation for mocking static methods

  
      
  1. 在测试用例的类级别使用@PrepareForTest( ClassThatContainsStaticMethod.class )注释
  2.   

到目前为止,我们知道我们需要准备测试A.class(静态方法)&你做了B.class(构造函数),但是你在类级别和测试方法级别都使用了@PrepareForTest

3)Powermock javadoc for @PrepareForTest

  

此注释可以放在测试类和单独的测试方法中。如果放在类中,则此测试类中的所有测试方法都将由PowerMock处理(以允许可测试性)。 要覆盖单个方法的此行为,只需在特定测试方法上放置@PrepareForTest注释即可。 这在例如您想要在测试方法A中修改类X但在测试方法B中希望X保持原样的情况下非常有用。

总之,要么在班级使用@PrepareForTest({A.class, B.class}),要么在方法层面使用,一切都应该没问题。