2017-09-26 248 views
2

我正在编写一个测试,以验证我的类在接收来自SOAP服务的不同响应时的行为。 我使用JAXB,所以我的回应包含JaxbElements,对于他们来说,我需要写一个假,这样的:Mockito模拟方法内的对象

JAXBElement<String> mock1 = mock(JAXBElement.class); 
when(mock1.getValue()).thenReturn("a StringValue"); 
when(result.getSomeStringValue()).thenReturn(mock1); 

JAXBElement<Integer> mock2 = mock(JAXBElement.class); 

when(mock2.getValue()).thenReturn(new Integer(2)); 
when(result.getSomeIntValue()).thenReturn(mock2); 
... <continue> 

什么,我想这样做,是refactorize这段代码的方式:

when(result.getSomeStringValue()) 
    .thenReturn(mockWithValue(JAXBElement.class, "a StringValue"); 

when(result.getSomeIntValue()) 
    .thenReturn(mockWithValue(JAXBElement.class, 2)); 

,并定义一个方法:

private <T> JAXBElement<T> mockWithValue(Class<JAXBElement> jaxbElementClass, T value) { 
    JAXBElement<T> mock = mock(jaxbElementClass); 
    when(mock.getValue()).thenReturn(value); 
    return mock; 
} 

当我执行的代码重构一切正常了。 不幸的是,当我重构之后执行所述的代码,我收到此错误:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at com.mypackage.ResultConverterTest.shouldConvertASuccessfulResponseWithAllTheElements(ResultConverterTest.java:126) 

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! 
    3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed 

其中线126是mockWithValue方法的第一次调用。

所以问题是:有没有一种方法可以重复使用相同的代码来创建许多具有类似行为的模拟?

+0

由于JAXB生成类是没有任何商业行为简单的DTO你不应该嘲笑他们...... –

+0

因为构建它们需要其他对象(Qname名称,类 declaredType,Class scope,T值),并且它的可读性会下降。无论如何,我可以做到这一点,但我遇到了这个例外,我想了解它。 – marco

回答

1

您不应该在创建响应时进行模拟。

让我解释一下,这个代码

private <T> JAXBElement<T> mockWithValue(Class<JAXBElement> jaxbElementClass, T value) { 
    JAXBElement<T> mock = mock(jaxbElementClass); 
    when(mock.getValue()).thenReturn(value); 
    return mock; 
} 

你嘲笑JAXBElement<T> mock = mock(jaxbElementClass),然后你在return响应使用此方法完成。

您应该先分别创建这些响应,然后在return内使用它们。

String stringResponse=mockWithValue(JAXBElement.class, "a StringValue"); 
when(result.getSomeStringValue()).thenReturn(stringResponse); 

试试这个,它会工作。

+1

我仍然不明白为什么,但是,它的工作原理!谢谢! – marco

+0

另请参阅提示#3 3:如果完成 –

2

当涉及到一些额外的仿制药的参与,同时嘲讽这是更好地去为doReturn()..when()语法:

doReturn(mockWithValue(JAXBElement.class, "a StringValue")) 
     .when(result).getSomeStringValue(); 

    doReturn(mockWithValue(JAXBElement.class, 2)) 
     .when(result).getSomeIntegerValue(); 

private <T> JAXBElement<T> mockWithValue(Class<JAXBElement> jaxbElementClass, T value) { 
     JAXBElement<T> mock = mock(jaxbElementClass); 
     doReturn(value).when(mock).getValue(); 
     return mock; 
    } 
+0

这就是我正在寻找的内容,那么您在“返回”指令之前将另一个模拟内容的行为存起来,谢谢! – marco