PowerMockito如何在SpringBoot中模拟私有方法

4

我正试图模拟我的测试类中的私有方法,代码如下。

public String processPayment(...) {
    //some lines
    privateMethod(...);
    return "";
}

private Object privateMethod(...) {
    //some lines
    return someObject;
}

现在,我需要测试processPayment方法并模拟privateMethod
我尝试创建上述类的spy,但是当我执行以下操作时,该方法被调用了。
final DeviceCheckoutServiceImpl spyDeviceCheckoutService = spy(injectedMockBeanOfAboveClass); //@InjectMock in test class
PowerMockito.doReturn(null).when(spyDeviceCheckoutService, "privateMethod", ArgumentMatchers.anyMap()); //method gets called here
spyDeviceCheckoutService.processPayment(...); //private method isn't mocked somehow, and gets called here too

privateMethod 在第二行就被调用了。而且 privateMethod 没有被模拟。

也许我创建 spy 对象的方式不正确?不能像这样做 spy(new DeviceCheckoutServiceImpl());,因为它需要 bean 实例化。

Powermockito 版本:

compile group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.0'
compile group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.0'

请告诉我在这里做错了什么。
3个回答

8

在测试类中,我们将通过传递需要被测试的类的引用来调用org.powermock.api.mockito.PowerMockito的spy()方法:

MockPrivateMethodExample spy = PowerMockito.spy(mockPrivateMethodExample);

接下来,我们定义当调用此特定私有方法时要执行的操作。

PowerMockito.doReturn("Test").when(spy, {$methodName});

MockPrivateMethodExample.java

public class MockPrivateMethodExample {

  public String getDetails() {
    return "Mock private method example: " + iAmPrivate();
  }

  private String iAmPrivate() {
    return new Date().toString();
  }
}

MockPrivateMethodTest.java

@RunWith(PowerMockRunner.class)
@PrepareForTest(MockPrivateMethodExample.class)
public class MockPrivateMethodTest {

  private MockPrivateMethodExample mockPrivateMethodExample;

  // This is the name of the private method which we want to mock
  private static final String METHOD = "iAmPrivate";

  @Test
  public void testPrivateMethod() throws Exception {
    mockPrivateMethodExample = new MockPrivateMethodExample();

    MockPrivateMethodExample spy = PowerMockito.spy(mockPrivateMethodExample);
    PowerMockito.doReturn("Test").when(spy, METHOD);
    String value = spy.getDetails();

    Assert.assertEquals(value, "Mock private method example: Test");
    PowerMockito.verifyPrivate(spy, Mockito.times(1)).invoke(METHOD);
  }
}

更多细节请查看:https://examples.javacodegeeks.com/core-java/mockito/mockito-mock-private-method-example-with-powermock/

1
已经尝试过了。每当我执行 PowerMockito.doReturn("Test").when(spy, METHOD); 时,该方法都会被调用,但是该方法并没有被模拟。 :-/ - Praveen Kamath
@PraveenKamath,您能否将答案标记为有用?谢谢。 - Mebin Joe

4
问题已解决! 我忘记在测试类上添加@PrepareForTest(DeviceCheckoutServiceImpl.class)了。

0

Mockito引入了AdditionalAnswers.delegatesTo,以支持对Spring代理和其他类似的事物进行跟踪:

请查看此问题: https://github.com/mockito/mockito/issues/529#issuecomment-239494581

因此,您可以使用mock(TestSubject.class, delegatesTo(springProxy)),而不是spy(proxy)

但是,如果需要读取注释,则需要使用Mockito 2 beta。因为mockito 1.x使用CGLIB,它不会将注释复制到mockito子类中。 Mockito 2使用了很棒的bytebuddy。


2
发现问题了。测试类上没有添加@PrepareForTest(DeviceCheckoutServiceImpl.class) - Praveen Kamath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接