Використання PowerMockito.whenNew () не висміюється і викликається оригінальний метод


100

У мене є код приблизно такий, як показано нижче:

Class A {
  public boolean myMethod(someargs) {
    MyQueryClass query = new MyQueryClass();
    Long id = query.getNextId();
    // some more code
  }
}
Class MyQueryClass     {
  ....
  public Long getNextId() {
    //lot of DB code, execute some DB query
    return id;
  }
}

Зараз я пишу тест для A.myMethod(someargs). Я хочу пропустити реальний метод query.getNextId()і замість цього повернути значення заглушки. В основному, я хочу знущатися MyQueryClass.

Отже, у своєму тестовому прикладі я використав:

MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);

boolean b = A.getInstance().myMethod(args);

//asserts

Я використовував @RunWith(PowerMockRunner.class)і @PrepareForTest({MyQueryClass.class})на початку свого тестового заняття.

Але коли я налагоджувати тест, він по - , як і раніше називати реальний метод getNextId()в MyQueryClassкласі.

Чого мені тут не вистачає? Хто-небудь може допомогти, оскільки я новачок у Mockito та PowerMockito.

Відповіді:


220

Вам потрібно помістити клас, де конструктор викликається, в @PrepareForTestанотацію замість класу, який будується - див. Макет побудови нових об’єктів .

У вашому випадку:

@PrepareForTest(MyQueryClass.class)

@PrepareForTest(A.class)

Більш загально:

@PrepareForTest(NewInstanceClass.class)

@PrepareForTest(ClassThatCreatesTheNewInstance.class)


1
Дуже дякую. Зараз він спрацював після включення поточного класу, наприклад, A до @PrepareForTest.
user3942446

2
Я витрачаю на це теж час. Дякую @TrueDub. Оскільки посилання застаріле. Я просто оновлюю це. github.com/jayway/powermock/wiki/MockConstructor У ньому сказано: Використовуйте анотацію @PrepareForTest (ClassThatCreatesTheNewInstance.class) на рівні класу тестового випадку.
Віктор Чой,

4
У мене така сама проблема, але це рішення для мене не працює
Декстер

3
Це рішення просто не буде працювати, якщо ви використовуєте eclemma для покриття коду. Додавання тестованого класу до @PrepareForTest призведе до 0% покриття для цього класу
ACV

2
Рішення буде працювати - тест виконується правильно. Очевидно, що eclemma не в змозі мати справу з PowerMockito. Висвітлення коду не є частиною цього питання.
TrueDub

3

Як @TrueDub згадував у своїй прийнятій відповіді, вам потрібно додати клас, куди викликається конструктор, до @PrepareForTest.

Однак якщо ви зробите це, охоплення для цього класу, як повідомляють eclemma та Sonar, буде для цього класу нульовим

Вікі про Powermockito

Ми збираємось замінити Javassist на ByteBuddy (# 727), і це повинно допомогти вирішити цю стару проблему. Але зараз НЕМАЄ СПОСОБУ ВИКОРИСТОВУВАТИ PowerMock з польовими приладами JaCoCo. І жодних обхідних шляхів для отримання покриття коду в IDE.

Тож рішенням тут буде рефакторинг фактичного коду для використання статичної фабрики, яка поверне екземпляр цього класу, а потім статично знущається над ним.


Погодився з вашим коментарем.
Леті

Однак це не проблема в Intellij.
ACV

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.