marco
marco

Reputation: 681

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?

Upvotes: 3

Views: 4356

Answers (2)

Maciej Kowalski
Maciej Kowalski

Reputation: 26572

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

Upvotes: 3

Dhawal Kapil
Dhawal Kapil

Reputation: 2767

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.

Upvotes: 2

Related Questions