即使在添加@PrepareForTest之后,Mockito也要求为该类添加@PrepareForTest

ViV*_*ViV 19 java mockito powermock

我有以下简单的代码.我有一个类(TestClass),我想测试"someMethod".有一个外部静态方法,由我的"someMethod"调用.我想Powermock那个静态方法给我一些虚拟对象.我在开头有@PrepareForTest(ExternalClass.class),但是当我执行它时会给出错误:

ExternalClass类没有准备好进行测试.要准备此类,请将类添加到'@PrepareForTest'注释中.如果您不使用此批注,请在类或方法级别添加批注.

请帮我指出我使用的方式有什么问题 @PrepareForTest

@RunWith(PowerMockRunner.class)
@PrepareForTest(ExternalClass.class)
public class xyzTest {  
    @Mock
    private RestTemplate restTemplate;

    @Mock
    private TestClass testClass;

    @BeforeClass
    private void setUpBeforeClass() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testSuccessCase() {
        Boolean mockResponse = true;
        ResponseEntity<Boolean> response = new ResponseEntity<Boolean>(mockResponse, HttpStatus.OK);
        SomeClass someClass = new SomeClass("test", "1.0.0", "someUrl", "someMetaData");

        PowerMockito.mockStatic(ExternalClass.class);

        Mockito.when(restTemplate.postForEntity(any(String.class), any(String.class), eq(Boolean.class))).thenReturn(response);
        Mockito.when(ExternalClass.getSomeClass(any(String.class))).thenReturn(someClass);

        Boolean result = testClass.someMethod("test");

        Assert.isTrue(result);
        Mockito.verify(restTemplate, times(1)).postForObject(any(String.class), any(String.class), any());
    }
}
Run Code Online (Sandbox Code Playgroud)

wil*_*ing 18

确保您也添加@RunWith(PowerMockRunner.class)到班级的顶部.

  • 这个答案没有帮助。即使大多数时候您不应该模拟静态方法,但如果您不拥有该代码,则将静态方法转换为实例方法 (1) 可能是不可能的,并且 (2) 可能会使代码更容易出错。不模拟状态的最可能的结果是不针对调用静态方法的代码编写测试。情况更糟。 (14认同)
  • 我非常同意@Vroo。我就面临这样一个案例,Apache 很高兴地违反了所谓的 SOLID 原则!这两天我一直在为这件事伤透脑筋。太糟糕了,这个答案已经成为热门话题…… (2认同)

小智 12

对于那些试图与 Junit 5 一起使用的人,如果您使用powermock-module-junit4声称与 4+ 兼容的beta 版本,该库仍将无法识别:

import org.junit.jupiter.api.Test;
Run Code Online (Sandbox Code Playgroud)

它会抛出一个:

org.powermock.api.mockito.ClassNotPreparedException
Run Code Online (Sandbox Code Playgroud)

when@PrepareForTest应用于要静态模拟的类。如果您想使用 PowerMock,此时您必须回到 Junit 4 或为您的静态方法创建一个 MockWrapper。

PowerMock 2.0:Github 路线图


Eug*_*ene 8

虽然这里评分最高的答案毫无疑问是正确的,但这并没有回答为什么需要这样的问题;或者,例如,为什么添加@RunWith(MockitoJUnitRunner.class).

事情是PowerMockRunner在引擎盖下使用检测 API,通过 javassist库,这允许更改类,如删除final或模拟static(非编译时常量)。

在修改(检测)某个类的过程中,他们添加了一个接口,称为PowerMockModified. 它是一个标记接口,表示发生了某个字节码检测。在代码的后面,他们只是@PrepareForTest通过这样的方法检查您使用的类是否实际上以某种方式进行了检测:

    private boolean isModifiedByPowerMock() {
        return PowerMockModified.class.isAssignableFrom(this.type);
    }
Run Code Online (Sandbox Code Playgroud)

事实证明,PowerMockRunner 它做了一些检测,而MockitoJUnitRunner没有;因此你得到的错误。


小智 5

与最后一个答案一样,我的问题还在于混合了TestNG的Test注释而不是Junit Test。

import org.junit.Test; // works

import org.testng.annotations.Test // did not work
Run Code Online (Sandbox Code Playgroud)

非常严重的错误,我花了5多个小时进行调试:(


Fel*_*tha 5

我有同样的错误,通过添加解决了这个问题

@Rule
public PowerMockRule rule = new PowerMockRule();
Run Code Online (Sandbox Code Playgroud)

在测试类里面.


小智 5

检查是否导入org.junit.Test;包已导入,而不是 api jupiter 之一。