简体   繁体   English

看起来正确的doThrow中的Mockito异常

[英]Mockito exception in doThrow that looks correct

I'm trying to mock a method to see if I handle an exception correctly. 我正在尝试模拟一个方法,看看我是否正确处理异常。 This is as far as I get. 这是我得到的。

interface: 接口:

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);

result: 结果:

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.

From an identical issue that I just ran into, I suspect that sample is a mock, and you stubbed sample.getId() elsewhere? 从我遇到的一个相同的问题,我怀疑sample是一个模拟,你在其他地方存在sample.getId()吗? That caused this problem in my case, anyhow. 无论如何,这在我的情况下造成了这个问题。

For some reason, Mockito gets upset if one of the arguments you pass to the stub used with doThrow in this way is the result of a method you also mocked. 出于某种原因,如果以这种方式传递doThrow一起使用的存根的其中一个参数是您也doThrow的方法的结果,Mockito会感到沮丧。 Perhaps it's a re-entrancy check of sorts to avoid infinite loops, I don't know. 我不知道,这可能是为了避免无限循环而进行的重新检查。

Regardless, try replacing sample.getId() with a constant value and that should solve the issue. 无论如何,尝试用常量值替换sample.getId() ,这应该可以解决问题。 You could consider using a constant declared in your test for both the mock and any further uses of it. 你可以考虑在你的测试中使用一个常量来模拟它和它的任何进一步用途。 You could then also check that sample.getId() was used by the method you're testing by adding another call to verify . 然后,您还可以通过添加另一个要verify调用来verify您正在测试的方法是否使用了sample.getId()

This error is usually reported AFTER the place where it actually occurred. 此错误通常在实际发生的位置后报告。 If you fail to stub something properly, Mockito usually can't tell until the NEXT time you call one of the Mockito methods. 如果你没有正确地存根,Mockito通常无法分辨,直到你下一次调用Mockito方法之一。 This might be in the same test method, a later test method in the same class, or even an entirely different test class. 这可能是在同一个测试方法中,在同一个类中的后续测试方法,或者甚至是完全不同的测试类。

The line that you've quoted looks fine to me. 你引用的那条线对我来说很好看。 Take a look at the lines above it, where you call a Mockito stubbing or verification method. 看看它上面的线条,你可以称之为Mockito存根或验证方法。 It's very likely that you have a when that has no associated thenReturn , then or thenThrow . 这很可能是你有一个when不具有关联thenReturnthenthenThrow Or you might have a verify that's missing the actual method call. 或者您可能verify缺少实际的方法调用。 There are a few other possibilities too. 还有其他一些可能性。

If you can't find an error in the lines ABOVE the one that you've quoted, then post some more of your code, and I'll take a closer look. 如果你在上面引用的那行中找不到错误,那么发布一些你的代码,我会仔细看看。

As described in the answer by Gijs, this is probably due to a bug in Mockito. 正如Gijs的回答所述,这可能是由于Mockito的一个错误。 Here is a complete test which reproduces it: 这是一个完整的测试,可以重现它:

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");
}

The test produces the following output: 测试产生以下输出:

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)

you have to supply an instance of the Exception.class not the Exception class itself. 你必须提供Exception.class的一个实例而不是Exception类本身。

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

EDIT Well @DavidWallace corrected me, so be warned (or rather enlightened) that since 1.9 you can just provide the exception class to throw and it will construct one for you. 编辑好@DavidWallace纠正了我,所以要警告(或者说更开明),因为1.9你可以提供抛出的异常类,它将为你构建一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM