Использование PowerMockito.whenNew () не издевается, и вызывается оригинальный метод


103

У меня есть примерно такой код ниже:

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.

Ответы:


226

Вы должны поместить класс , где конструктор вызывается в @PrepareForTestаннотацию вместо класса , который строится - см Mock строительства новых объектов .

В твоем случае:

@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 08

3

Как отметил @TrueDub в своем принятом ответе, вам нужно добавить класс, в котором вызывается конструктор, в @PrepareForTest.

Однако, если вы сделаете это, покрытие для этого класса, как сообщает eclemma и Sonar, будет нулевым для этого класса.

Powermockito вики

Мы собираемся заменить Javassist на ByteBuddy (# 727), и это должно помочь решить эту старую проблему. Но прямо сейчас НЕЛЬЗЯ ИСПОЛЬЗОВАТЬ PowerMock с инструментами JaCoCo On-the-fly. И нет обходного пути для покрытия кода в IDE.

Таким образом, решением здесь было бы рефакторинг фактического кода для использования статической фабрики, которая возвращала бы экземпляр этого класса, а затем статически имитировала бы его.


Согласен с вашим комментарием.
долговязый

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.