Mockito模拟方法内的对象

时间:2017-09-26 10:25:19

标签: java unit-testing mocking mockito

我正在编写一个测试,用于在从SOAP服务接收不同的响应时验证我的类的行为。 我使用Jaxb,所以我的回复包含PlotCast.find({ owner: 'winery' }).lean().exec(function(err, results) { if (err) { res.send(err); } else if (!results) { res.send(null); } else { res.send(results); } }); ,对于其中许多人,我需要编写一个模拟,如:

JaxbElements

我想做的是以这种方式重构这段代码:

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>

并定义一个方法:

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

其中第126行是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 方法的第一次调用。

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

2 个答案:

答案 0 :(得分: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;
    }

答案 1 :(得分: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);

试试这个,它会起作用。