Подтвердить что ты не робот

Mockito дает UnfinishedVerificationException, когда кажется ОК

Mockito, похоже, выбрасывает UnfinishedVerificationException, когда я думаю, что все сделано правильно. Здесь мой частичный тестовый пример:

HttpServletRequest req = mock(HttpServletRequest.class);
when(req.getHeader("Authorization")).thenReturn("foo");

HttpServletResponse res = mock(HttpServletResponse.class);

classUnderTest.doMethod(req, res); // Use the mock

verify(res, never());
verify(req).setAttribute(anyString(), anyObject());

И вот частичный класс и метод:

class ClassUnderTest extends AnotherClass {
    @Override
    public String doMethod(ServletRequest req, ServletRequest res) {
        // etc.
        return "someString";
    }
}

Игнорируя тот факт, что вы никогда не должны издеваться над интерфейсами, которыми вы не владеете, почему Mockito дает мне следующее сообщение?

org.mockito.exceptions.misusing.UnfinishedVerificationException: 
Missing method call for verify(mock) here:
-> at (redacted)

Example of correct verification:
    verify(mock).doSomething()

Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.

at [test method name and class redacted]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
... etc
4b9b3361

Ответ 1

Я только что столкнулся с этим сам, и это вызвало у меня много путаницы.

Как упоминал Дэвид, Mockito сообщает об ошибках при следующем вызове метода Mockito, которые могут отсутствовать в том же методе тестирования. Хотя сообщение об исключении содержит ссылку на фактическое место, где произошла ошибка, я обнаружил, что неправильные тесты не дают результатов в процессе тестирования. И чем проще тесты, тем больше вероятность появления ошибки в следующем тесте!

Вот простое исправление, которое обеспечит появление ошибок в правильном методе теста:

@After
public void validate() {
    validateMockitoUsage();
}

Из документации Mockito здесь:

Mockito генерирует исключения, если вы его неправильно используете, чтобы вы знали, правильно ли написаны ваши тесты. Суть в том, что Mockito выполняет валидацию при следующем использовании фреймворка (например, при следующей проверке, заглушке, вызове макета и т.д.). Но даже если исключение может быть выдано в следующем тесте, сообщение об исключении содержит элемент трассировки стека с возможностью навигации с указанием местоположения дефекта. Следовательно, вы можете нажать и найти место, где Mockito был использован не по назначению.

Иногда, однако, вы можете явно проверить использование фреймворка. Например, один из пользователей хотел добавить validateMockitoUsage() в свой метод @After, чтобы он сразу знал, когда он неправильно использовал Mockito. Без этого он узнал бы об этом не раньше, чем в следующий раз, когда использовал фреймворк. Еще одно преимущество наличия validateMockitoUsage() в @After заключается в том, что бегун jUnit всегда будет терпеть неудачу в методе тестирования с дефектом, в то время как обычная проверка в следующий раз может провалиться при следующем методе тестирования. Но даже несмотря на то, что JUnit может сообщить о следующем тесте как красный, не беспокойтесь об этом и просто нажмите на отслеживаемый элемент стека в навигационном сообщении, чтобы мгновенно найти место, где вы неправильно использовали mockito.

Ответ 2

Это также может быть вызвано, если вы попробуете verify метод, который ожидает примитивные аргументы с any():

Например, если наш метод имеет такую ​​подпись:

method(long l, String s);

И вы попытаетесь проверить его так: он не сработает с вышеупомянутым сообщением:

verify(service).method(any(), anyString());

Измените его на anyLong(), и он будет работать:

verify(service).method(anyLong(), anyString());

Ответ 3

Я получал эту же ошибку из-за использования any() с boolean параметром, когда, очевидно, это должен был быть anyBoolean().

Ответ 4

Для меня проблема оказалась отсутствующим объявлением bean-компонента в тестовом контексте xml. Это было для пользовательского класса аспектов, используемого другим классом, экземпляр которого является параметром для конструктора класса, который является параметром неудачного вызова verify(). Поэтому я добавил объявление bean-компонента в контекст xml, и после этого оно работало нормально.

Ответ 5

У меня было подобное исключение с классом MyRepository

org.mockito.exceptions.misusing.UnfinishedVerificationException: Отсутствует метод вызова для проверки (mock) здесь: → в MyRepository $$ FastClassBySpringCGLIB $$ de8d8358.invoke()

Пример правильной проверки:

verify(mock).doSomething()

Проблема была решена, когда я создал интерфейс для MyRepository и макет интерфейса, но не реализацию. Кажется, что spring создает некоторые прокси CGLIB и приводит к исключению UnfinishedVerificationException.

Ответ 6

У меня была похожая проблема, я нашел способ решить эту проблему. Поддельные объекты, которые вы проверяете, не были сброшены, поэтому вы должны сбросить их. Вы можете сбросить (смоделировать) перед функцией тестового случая, это может быть полезно.

Ответ 7

С Junit 5 вы можете добавить следующее, чтобы показать более значимые исключения Mockito в консоли

@AfterEach
public void validate() {
    validateMockitoUsage()
}

Также смотрите этот ответ: fooobar.com/questions/237581/...

Ответ 8

Если вы попытаетесь проверить закрытый или закрытый для пакета метод с помощью Mockito.verify, вы получите эту ошибку.

Если вы не хотите использовать PowerMockito, вы можете установить свой метод как защищенный, и я советую вам добавить тег @VisibleForTesting:

До:

void doSomething() {
   //Some behaviour
}

После:

@VisibleForTesting
protected void doSomething() {
   //Some behaviour
}

Ответ 9

У меня была такая же ошибка

org.mockito.exceptions.misusing.UnfinishedVerificationException: 
Missing method call for verify(mock) here:
-at com.xxx.MyTest.testRun_Should_xxx_When_yyy(MyTest.java:127)

Example of correct verification:
    verify(mock).doSomething()

Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.


    at com.xxx.MyTest.validate(MyTest.java:132)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.internal.runners.MethodRoadie.runAfters(MethodRoadie.java:145)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:99)
...

В моем случае ошибка была вызвана тем, что я использовал PowerMockito.verifyStatic() перед моим вызовом Mockito.verify(...), затем мне пришлось переместить PowerMockito.verifyStatic() в последнюю строку (или удалить ее).

От:

PowerMockito.verifyStatic();
Mockito.verify(myMock, Mockito.times(1)).myMockedMethod(anyString(), anyString(), anyString(), any(XXX.class), any(YYY.class), any(ZZZ.class));

Для того, чтобы:

Mockito.verify(myMock, Mockito.times(1)).myMockedMethod(anyString(), anyString(), anyString(), any(XXX.class), any(YYY.class), any(ZZZ.class)); 
PowerMockito.verifyStatic();

Ответ 10

Я не уверен, где ваш "classUnderTest" пришли, но, пожалуйста, держите, что он издевался, а не реальный. У меня та же проблема для моего теста ниже:

MyAgent rpc = new MyAgent("myNodeName");
...
rpc.doSomething();
...
PowerMockito.verifyPrivate(rpc).invoke("initPowerSwitch");
PowerMockito.verifyPrivate(rpc).invoke("init", "192.168.0.23", "b2", 3);

Но он исчез для следующего теста:

MyAgent rpc = PowerMockito.spy(new MyAgent("myNodeName"));
...
rpc.doSomething();
...
PowerMockito.verifyPrivate(rpc).invoke("initPowerSwitch");
PowerMockito.verifyPrivate(rpc).invoke("init", "192.168.0.23", "b2", 3);

Внимание, объект RPC должен быть смоделирован PowerMockito.spy(...).