3

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?

2
  • Since the JaxB generated classes are simple DTOs without any business behavior you should not mock them... Commented Sep 26, 2017 at 10:34
  • Because build them requires other objects (Qname name, Class<T> declaredType, Class scope, T value) and it loses in readability. Anyway, I can do that, but I bumped into this exception, and I'd like to understand it. Commented Sep 26, 2017 at 10:38

2 Answers 2

3

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;
    }
Sign up to request clarification or add additional context in comments.

Comments

2

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.

2 Comments

I still don't understand why, but yes, it works! Thank you!
See also hint # 3 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.