简体   繁体   English

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

[英]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. 我正在编写与第三方Java SDK接口的应用程序。 I'm currently using Mockito and PowerMock to write unit tests. 我目前正在使用Mockito和PowerMock编写单元测试。 I'm running into a problem mocking the classes provided by the sdk. 我在模拟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. 我正在尝试模拟B类,该类同时调用A的构造函数和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: 我需要能够在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();

    }

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:) 但是,如果我不尝试模拟构造函数(即,删除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();

    }  

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? Powermock是否有某些东西可以防止同时模拟构造函数和静态方法? 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) 用于模拟构造函数的Powermock文档

  1. Use the @PrepareForTest( ClassThatCreatesTheNewInstance.class ) annotation at the class-level of the test case. 在测试用例的类级别使用@PrepareForTest( ClassThatCreatesTheNewInstance.class )批注。

2) Powermock documentation for mocking static methods 2) Powermock文档,用于模拟静态方法

  1. Use the @PrepareForTest( ClassThatContainsStaticMethod.class ) annotation at the class-level of the test case 在测试用例的类级别使用@PrepareForTest( ClassThatContainsStaticMethod.class )批注

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. 到目前为止,我们知道我们需要为测试A.class (静态方法)和B.class (构造函数)做准备,但是您在类级别以及测试方法级别都使用了@PrepareForTest

3) Powermock javadoc for @PrepareForTest 3) Powermock的javadoc @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). 如果放置在一个类上,则该测试类中的所有测试方法都将由PowerMock处理(以实现可测试性)。 To override this behavior for a single method just place a @PrepareForTest annotation on the specific test method. 要覆盖单个方法的此行为,只需在特定的测试方法上放置@PrepareForTest批注。 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 . 例如,在您想在测试方法A中修改类X但在测试方法B中希望保留X不变的情况下,这很有用

In conclusion, either use @PrepareForTest({A.class, B.class}) at class level, or method level and everything should be fine. 总之,可以在类级别使用@PrepareForTest({A.class, B.class}) ,也可以在方法级别使用@PrepareForTest({A.class, B.class})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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