2012-08-29 16 views
15

我想模拟一个方法,看看我是否正确处理异常。这是我得到的。在doThrow Mockito异常看起来是正确的

接口:

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

单元测试:

// ... 
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. 

回答

0

,你必须提供一个实例Exception.class不是Exception类本身

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

编辑 好@DavidWallace纠正我,所以被警告(或相当开明),自1.9你可以提供异常类抛出,这将构建一个给你。

+2

不,从1.9.0的Mockito起,您可以提供异常类,这将作为预期。但是,即使OP使用旧版本的Mockito,他们也不会在这里描述他们描述的症状。我相信这个问题是不同的。 –

+0

谢谢大卫。不知道。我会在这里留下我的回答,以便其他人可以通过您的评论意识到。 –

4

该错误通常在实际发生的地点后报告。如果你没有正确地存储某些东西,Mockito通常无法分辨,直到下一次你调用其中一种Mockito方法。这可能在相同的测试方法中,在同一个类中的后续测试方法,或甚至完全不同的测试类。

你引用的那条线对我来说看起来很好。看看它上面的线,你可以在那里调用Mockito的stubbing或验证方法。很有可能您的when没有关联thenReturn,thenthenThrow。或者您可能有verify缺少实际的方法调用。还有其他一些可能性。

如果您在上面引用的行中找不到错误,请发布一些更多代码,然后仔细查看。

+1

另外,如果您使用JUnit runner'MockitoJUnitRunner.class',Mockito将检查您的测试方法是否没有任何未完成的存根。这将有助于将此错误隔离到问题的根源。 OP: – Brice

+0

如果你想确定它是否是问题,那很简单:只需运行特定的一种测试方法,你会发现它工作正常。或者,您可以在实际测试逻辑之前进行模拟重置,并且您可能会发现测试运行正常。这些是大卫华莱士描述的问题的症状 –

+0

但是问题实际上可能在相同的测试方法。所以你可能会得到只运行一种测试方法的错误。在这种情况下,使用'MockitoJUnitRunner'也无济于事。 –

17

从我刚刚碰到的一个相同的问题,我怀疑sample是一个模拟,你在其他地方凿了sample.getId()?无论如何,这在我的情况下造成了这个问题。

由于某种原因,如果您以这种方式传递到与doThrow一起使用的存根的某个参数是您也嘲笑的方法的结果,那么Mockito会不高兴。也许这是为了避免无限循环而进行的重新检查,我不知道。

无论如何,尝试用一个常数替换sample.getId(),这应该可以解决问题。你可以考虑在你的测试中使用一个常量来声明模拟和它的任何进一步的用法。然后您可以通过添加对verify的另一个调用来检查您正在测试的方法是否使用了sample.getId()

+0

我面临同样的问题..解决它通过不传递一个常数值而不是一个模拟。 –

+0

谢谢你!我通过传递'thenReturn'方法来解决它,而不是直接从getter中获取值。 – Juancho

4

正如Gijs的回答中所述,这可能是由于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) 
+0

如果是这样,那么简单的解决方法是:'doThrow(Exception.class).when(manager).deleteVariome(“a”,“b”);' –