Mock an Interface with Mockito return a NullPointerException

Viewed 6094

I m trying create unit tests for one project.I m facing a problem because when I try control the result of an interface(mock). When the code get the Interface variable that return a NullPointerException.

Firstly I tried @Override the method in my test class (ClassA), but it don't work. After that I tried mock the interface object and control the comportment with Mockito.When().tehnReturn();

I will put here my code, I read some solutions but none works.

My Interface:

    @FunctionalInterface
    public interface Interface {
        UpdateXResponse process(UpdateXRequest request) throws Exception;
    }

The class I want to test:

    @Service(ClassA.class)
    public class ClassA extends VService implements UpdateX {

        @Reference
        @Inject
        private Interface interface;

        @Inject
        public ClassA(...) {...}

        @Override
        public UpdateXResponse process(UpdateXRequest request) throws Exception {
            UpdateXResponse response = initResponse(context, request, new UpdateXResponse());
            UpdateXInput input = request.getInput();
            UpdateXOutput output = new UpdateXOutput();
            response.setOutput(output);

            try {
                firstMethodCall(...);

            } catch (Exception t) {
                throwCorrectException(t, logger);
            }
            return response;
        }

        private void firstMethodCall(...) throws Exception {
            TypeF typeF = callInterfaceMethod(...);
            ...
        }

        /**
         * Orchestrates Interface service
         */
        protected TypeF callInterfaceMethod(...) {
            ...
            request.setInput(input);
            request.setHeader(header);

            InterfaceResponse response = interface.process(request); // LINE ERROR - In this step interface is NULL when the test get this

            return response;
        }
    }

And finally my class test:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(value = {ClassA.class,Interface.class} )
    public class WithPowerMockUnitTest{

        @InjectMocks
        private ClassA classA;

        private Interface interface;

        @Before
        public void setUp() throws Exception {
            InterfaceRequest InterfaceRequest = createInterfaceRequest();
            InterfaceResponse serviceUnavailableResponse = createInterfaceResponse();

            Interface = Mockito.mock(Interface.class);
            when(Interface.process(Mockito.any(InterfaceRequest.class))).thenReturn(serviceUnavailableResponse);  
        }

        @Test
        public void testh() throws SOAException {
            InterfaceResponse res = interface.process(Mockito.any(InterfaceRequest.class)); // There all run ok. The interface is not null and return what i expected.
            System.out.println("RES "+res);
        }
        @Test
        public void test() {
            assertNotNull(classA);  // not null
            assertNotNull(interface); // not null
        }

        @Test
        public void newTest() throws Exception {

            InterfaceRequest InterfaceRequest = createInterfaceRequest();
            InterfaceResponse serviceUnavailableResponse = createInterfaceResponse();

            UpdateXResponse response = ClassA.process(updateXRequest()); // PROBLEM!! When that get the LINE ERROR the interface is null! WHY?      
        }
    }

I put some comments in the lines where the problem exists for me.


    public interface A{
        Response process(Request r) throws Exception;
    }

    public class B{

    private Class_That_Override_Interface_method  ctoim;

        public Response function(){
          X res = method_B();
        }
        protected X method_B(){
          response res = ctoim.process(request); // That ctoim is always NULL when the test get that line/call
        }

    }

Thanks

1 Answers

You're missing the @Mock annotation on your Interface variable. Therefore the mock is not injected into your classA and the newTest() fails. (In this case remove Interface = Mockito.mock(Interface.class); from the setUp method).

Alternativly remove the @InjectMocks annotation and create your class under test manually passing your mock into the constructor.


For this specific case (assuming its a different case from the last question) there doesn't seem to be a need to involve PowerMockito. So unless you left out some relevant parts you might as well just use the MockitoJUnitRunner.


Ps.: Also remeber what I said last time about compilable examples?

  • interface is a keyword and can't be used for variables.
  • You should also aim to write variables identical all the times (not Interface and interface / classA and ClassA)

And in case you haven't read it yet check out the help section about minmal reproducible examples.


Edit:

I fogot to mention that the line interface.process(Mockito.any(InterfaceRequest.class)); in testh() is actually invalid syntax. You should use ArgumentMatchers only for parameters of mocked methods.

Also consider adding the MockitoAnnotations.initMocks(this); to your setUp method, when using the PowerMockRunner.

Related