简体   繁体   中英

Mockito mock objects inside a method

I am writing a test for verifying the behavior of my class when receiving different responses from a SOAP Service. I use Jaxb, so my response contains JaxbElements , and for many of them, I need to write a mock, like that:

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>

what I would like to do, is refactorize this code that way:

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

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

and define a method:

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

when I execute the code before the refactoring everything works properly. Unfortunately, when I execute the the code after the refactoring, I receive this error:

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

where line 126 is the first invocation of the mockWithValue method.

So the question is: is there a way to reuse the same code in order to create many mocks with similar behavior?

When it comes to some additional generics involvement while mocking it is better to go for the doReturn()..when() syntax:

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

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

and

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

You should not mock while creating response.

Let me explain, in this code

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

you are mocking JAXBElement<T> mock = mock(jaxbElementClass) and then you are using this complete method in return response.

You should first created these responses separately and then use them inside return .

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

Try this, it will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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