Исключение Mockito в doThrow, которое выглядит правильно

Я пытаюсь высмеять метод, чтобы проверить, правильно ли я обрабатываю исключение. Это насколько я понимаю.

интерфейс:

interface SampleManager {
    void deleteVariome(String specimenId, String analysisId) throws Exception;
    // ...
}

unit test:

// ...
SampleManger sampleManager = mock(SampleManager.class);

// below is line 753
doThrow(Exception.class).when(sampleManager).deleteVariome(sample1.getId(), analysisId);

результат:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at ...server.ArchiveManagerImplUTest.deleteVariomeFails(ArchiveManagerImplUTest.java:753)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod(); <-- this looks a log like what I did!

Hints:

 1. missing thenReturn()

 2. you are trying to stub a final method, you naughty developer! <-- I have a lot of other mocks of this interface in this test that work.

Ответы

Ответ 1

Из идентичной проблемы, с которой я только столкнулся, я подозреваю, что sample является макетом, и вы пропустили sample.getId() в другом месте? В любом случае это вызвало эту проблему в моем случае.

По какой-то причине Mockito расстраивается, если один из аргументов, которые вы передаете в заглушку, используемую с doThrow таким образом, является результатом метода, который вы также издевались. Возможно, это повторная проверка сортировки, чтобы избежать бесконечных циклов, я не знаю.

Независимо от того, попробуйте заменить sample.getId() на постоянное значение, и это должно решить проблему. Вы могли бы рассмотреть возможность использования константы, объявленной в вашем тесте, как для макета, так и для его дальнейшего использования. Затем вы также можете проверить, что метод sample.getId() использовался методом, который вы тестируете, добавив еще один вызов verify.

Ответ 2

Эта ошибка обычно сообщается ПОСЛЕ того места, где она на самом деле произошла. Если вы не закроете что-то должным образом, Mockito обычно не может сказать, пока NEXT время вы не назовете одним из методов Mockito. Это может быть в одном методе тестирования, более позднем методе тестирования в том же классе или даже в совершенно другом тестовом классе.

Строка, которую вы цитировали, выглядит хорошо для меня. Взгляните на строки над ним, где вы называете метод Mockito stubbing или проверки. Очень вероятно, что у вас есть when, у которого нет связанных thenReturn, then или thenThrow. Или у вас может быть verify, в котором отсутствует фактический вызов метода. Есть еще несколько возможностей.

Если вы не можете найти ошибку в строках ABOVE, которую вы указали, добавьте еще несколько своих кодов, и я присмотрюсь ближе.

Ответ 3

Как описано в ответе Гиса, это, вероятно, связано с ошибкой в ​​Mockito. Вот полный тест, который воспроизводит его:

interface Sample { String getId(); }
interface SampleManager {
    void deleteVariome(String specimenId, String analysisId);
}

@Test
public void probableMockitoBug() {
    Sample sample1 = mock(Sample.class);
    when(sample1.getId()).thenReturn("a");

    SampleManager manager = mock(SampleManager.class);
    doThrow(Exception.class).when(manager).deleteVariome(sample1.getId(), "b");

    manager.deleteVariome("a", "b");
}

Тест производит следующий вывод:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at org.mockitousage.JavadocExamplesTest.probableMockitoBug(JavadocExamplesTest.java:404)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!

    at org.mockito.exceptions.Reporter.unfinishedStubbing(Reporter.java:55)
    at org.mockito.internal.progress.MockingProgressImpl.validateState(MockingProgressImpl.java:74)
    at org.mockito.internal.progress.ThreadSafeMockingProgress.validateState(ThreadSafeMockingProgress.java:49)
    at org.mockito.internal.MockHandler.handle(MockHandler.java:71)
    at org.mockito.internal.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:36)
    at org.mockito.internal.creation.MethodInterceptorFilter.intercept(MethodInterceptorFilter.java:48)
    at org.mockitousage.JavadocExamplesTest$Sample$$EnhancerByMockitoWithCGLIB$$d5ac41.getId()
    at org.mockitousage.JavadocExamplesTest.probableMockitoBug(JavadocExamplesTest.java:404)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)

Ответ 4

вам нужно предоставить экземпляр класса Exception.class не самого класса Exception.

doThrow(new Exception()).when(sampleManager).deleteVariome(sample1.getId(), analysisId);

ИЗМЕНИТЬ Ну @DavidWallace исправил меня, поэтому будьте предупреждены (или, скорее, просвещены), что с 1.9 вы можете просто предоставить класс исключения, чтобы бросить, и он построит его для вас.