Макет интерфейса с Mockito возвращает исключение NullPointerException - PullRequest
0 голосов
/ 28 октября 2019

Я пытаюсь создать модульные тесты для одного проекта. Я сталкиваюсь с проблемой, потому что, когда я пытаюсь контролировать результат интерфейса (макет). Когда код получает переменную Interface, которая возвращает исключение NullPointerException.

Сначала я попытался @Override метод в моем тестовом классе (ClassA), но он не работает. После этого я попытался смоделировать объект интерфейса и проконтролировать компиляцию с помощью Mockito.When (). TehnReturn ();

Я приведу здесь свой код, я прочитал некоторые решения, но ни одно из них не работает.

Мой интерфейс:

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

Класс, который я хочу протестировать:

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

И, наконец, мой класс:

    @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Поместите несколько комментариев в строки, где проблема существует для меня.


    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
        }

    }

Спасибо

1 Ответ

0 голосов
/ 28 октября 2019

Вам не хватает аннотации @Mock в переменной Interface. Поэтому макет не вводится в ваш classA, и newTest() терпит неудачу. (В этом случае удалите Interface = Mockito.mock(Interface.class); из метода setUp).

Альтернативно удалите аннотацию @InjectMocks и создайте тестируемый класс вручную, передав макет в конструктор.


В этом конкретном случае (если он отличается от предыдущего вопроса), похоже, нет необходимости привлекать PowerMockito. Так что, если вы не пропустили некоторые важные части, вы могли бы просто использовать MockitoJUnitRunner.


Ps .: Также помните, что я сказал в прошлый раз о compilable примерах?

  • interface является ключевым словом и не может использоваться для переменных.
  • Вы должны также стремиться писать переменные, идентичные все время (не Interface и interface/ classA и ClassA)

А если вы еще не прочитали его, ознакомьтесь с разделом справки о минимально воспроизводимых примерах .


Редактировать:

Я не могу упомянуть, что строка interface.process(Mockito.any(InterfaceRequest.class)); в testh() на самом деле неверный синтаксис. Вы должны использовать ArgumentMatchers только для параметров проверяемых методов.

Также рассмотрите возможность добавления MockitoAnnotations.initMocks(this); к вашему setUp методу при использовании PowerMockRunner.

...