Макет частных методов PowerMockito в springboot

#spring-boot #junit #mockito #powermock #powermockito

#весенняя загрузка #junit #mockito #powermock #powermockito

Вопрос:

Я пытаюсь имитировать частный метод внутри моего тестируемого класса, как показано ниже.

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

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

Теперь мне нужно протестировать processPayment метод и макет privateMethod .

Я попытался создать шпион вышеуказанного класса, но метод вызывается, когда я делаю ниже

 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 Вызывается на самой 2-й строке.
Кроме того, the privateMethod не издевается.

Может быть, я создаю объект-шпион неправильно? Не могу сделать spy(new DeviceCheckoutServiceImpl()); , поскольку для этого требуется создание экземпляра компонента.

Версия 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'
 

Дайте мне знать, что я здесь делаю не так.

Ответ №1:

В тестовом классе мы вызовем метод spy() org.powermock.api.mockito.PowerMockito , передав ссылку на класс, который необходимо протестировать:

 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); , плюс, метод не издевается. :-/

2. @PraveenKamath Не могли бы вы отметить ответ как полезный. Спасибо.

Ответ №2:

Проблема решена! Забыл добавить @PrepareForTest(DeviceCheckoutServiceImpl.class) тестовый класс.

Ответ №3:

Mockito введен AdditionalAnswers.delegatesTo для поддержки слежки за весенними прокси и другими подобными вещами:

Проверьте эту проблему: https://github.com/mockito/mockito/issues/529#issuecomment-239494581

Поэтому вместо spy(proxy) использования mock(TestSubject.class,
delegatesTo(springProxy))
.

Однако, если аннотации необходимо прочитать, вам понадобится бета-версия mockito 2. Потому что mockito 1.x использует CGLIB, который не копирует аннотации в подкласс mockito. В Mockito 2 используется отличный bytebuddy.

Комментарии:

1. Обнаружена проблема. Не добавлял @PrepareForTest(DeviceCheckoutServiceImpl.class) тестовый класс.