0
votes

I'm trying to mock a SOAP Interceptor class, where one of the class methods returns an Iterator object. However, after double checking the syntax, the iterator is not replaced with the real iterator, and Mockito continues to run the method without the real iterator.

I've tried mocking the return value of the interceptor using the various mockito methods (doReturn, when... thenReturn) and neither of the methods have worked. I'm not sure where my error is in my mocking.

Here is how I mock the current object within my test class:

@Mock private WebServiceTemplate template;
@Mock private SoapInterceptor interceptor;
@Mock private Iterator<Attachment> iterator;

    @Test
    public void testGetDocsSoapClient() {
        @SuppressWarnings("unchecked")
        Iterator<Attachment> realIterator = new ArrayListIterator();
        ObjectFactory realFactory = new ObjectFactory();

        assertFalse(realIterator.hasNext());

        doReturn(realFactory.createAwsGetDocsRequest(createMockAwsGetDocsReq()))
            .when(factory).createAwsGetDocsRequest(any (AwsGetDocsRequest.class));
        doReturn(realFactory.createAwsGetDocsResponse(createAwsGetDocsResponse()))
            .when(template).marshalSendAndReceive(any(Object.class), any(SoapActionCallback.class));
        doReturn(realIterator)
            .when(interceptor).getSoapAttachments();

Here is how the method is called within the real class.

Iterator<Attachment> soapAttachments = attachmentInterceptor.getSoapAttachments();
ImageListDVO imgList = convertToImageList(soapAttachments);

... and my test case fails at the last line of this private method.

private ImageListDVO convertToImageList(Iterator<Attachment> attachments) {
        ImageListDVO imgList = new ImageListDVO();

        while(attachments.hasNext()) {

I should be mocking the object correctly, but I am getting a NullPointerException, which indicates that the object is not being mocked nor injected correctly.

1
Why mock an iterator at all? Create a real iterator with Arrays.asList(/* whatever elements */).iterator().Andy Turner
@AndyTurner Hmm, even if I do this, the real iterator I created isn't injected properly into the mocked object. I do something similar within the test caseAndy Wong

1 Answers

0
votes

I think you are using the wrong syntax. If I understand correctly you need to mock the SoapInterceptor which has a method getSoapAttachments()

To do that you need to change your code to something like this:

    @InjectMocks
    // the class under test should be put here

    @Mock
    SoapInterceptor attachmentInterceptor;

    @Test
    public void testGetDocsSoapClient() {

       // this is either a real interceptor or a mocked version of it
       Iterator<Attachment> iterator = ... ;
       when(attachmentInterceptor.getSoapAttachments()).thenReturn(iterator);
    }

The do methods are normally used when you want to mock void methods.

You also wrote you already tried this, so its likely that you do not initialize Mockito correctly.


Make sure you use the proper Runner / Extension / Rule or whatever else there is (like MockitoAnnotations.initMocks(testClass)). There are certain differences between the JUnit version you might be using. (If you still need help with that provide the JUnit & Mockito Verison you are using).

(see https://static.javadoc.io/org.mockito/mockito-core/2.28.2/org/mockito/Mockito.html#9)


Another possibility that things are not injected might be that your class is structured in a way mockito can`t handle.

From your test case I would assume you used field injection, so the @Mock annotated field should have the same name as the private field you have in your Test Class. So once again I am not sure which one that is as you didn`t provide the name.

There should be a proper @InjectMocks annotation for this class you are using, unless you provide the Mocks manually. (But in this case you probably woudn`t use the @Mock annotation).



Edit:
Another interpretation of you question could be that you are the trying to test a method of the SoapInterceptor itself and you want to replace the method that returns the Iterator with something else.

In that case you should look into the creation of a Spy instead and your code should look like this:

    @Test
    public void testGetDocsSoapClient() {

        SoapInterceptor interceptor = new SoapInterceptor();
        SoapInterceptor spy = Mockito.spy(interceptor);

        when(spy.getSoapAttachments()).thenReturn(iterator);

        ...
    }