用 Mockito 模拟接口 return 一个 NullPointerException

Mock an Interface with Mockito return a NullPointerException

我正在尝试为一个 project.I 遇到问题创建单元测试,因为当我尝试控制接口(模拟)的结果时。当代码获取 return 一个 NullPointerException.

的接口变量时

首先我在我的测试class (ClassA) 中尝试了@Override 方法,但它不起作用。之后我尝试模拟接口对象并使用 Mockito.When().tehnReturn();

控制行为

我会把我的代码放在这里,我阅读了一些解决方案,但 none 有效。

我的界面:

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

我要测试的class:

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

最后是我的 class 测试:

    @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?      
        }
    }

我在存在问题的行中添加了一些注释。


    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
        }

    }

谢谢

您缺少 Interface 变量上的 @Mock 注释。 因此,模拟不会注入您的 classA 并且 newTest() 失败。 (在这种情况下,从 setUp 方法中删除 Interface = Mockito.mock(Interface.class);)。

或者删除 @InjectMocks 注释并创建你的 class 测试手动传递你的模拟到构造函数。


对于这个具体案例(假设它与上一个问题不同) PowerMockito 似乎没有必要参与。因此,除非您遗漏了一些相关部分,否则您不妨使用 MockitoJUnitRunner.


Ps.: 还记得我上次说的 compilable 个例子吗?

  • interface是关键字,不能用于变量。
  • 您还应该始终编写相同的变量(不是 Interfaceinterface / classAClassA

如果您还没有阅读它,请查看有关 minmal reproducible examples 的帮助部分。


编辑:

我忘了提 testh() 中的行 interface.process(Mockito.any(InterfaceRequest.class)); 实际上是无效语法。您应该仅将 ArgumentMatchers 用于模拟方法的参数。

在使用 PowerMockRunner.

时,还可以考虑将 MockitoAnnotations.initMocks(this); 添加到 setUp 方法中