JUnit 5 и Mockito assertThrows() вызывают исключение NullPointerException вместо исходного

Я хочу протестировать метод, который должен вызывать исключение типа MyCustomException. Это пример моего класса MyService.

public class MyService {
    public void invoke(InvocationContext ctx) throws MyCustomException{
        if (ctx == null) {
            throw new MyCustomException("Parameter ctx must not be null.");
        }
    }
}

Я хотел бы проверить, выдает ли метод MyCustomException, если я передаю нулевое значение с помощью assertThrows().

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class AxwApplicationTest {
    @Spy
    @InjectMocks
    MyService myServiceToTest;

    @Test
    public void invoke_ShouldThrow_MyCustomException() {
        assertThrows(MyCustomException.class, () -> {
            myServiceToTest.invoke(null);
        });
    }
}

Каким-то образом возникает исключение, но оно заканчивается как NullPointerException, и я не знаю, как его решить. assertThrows выдает следующую ошибку:

java.lang.AssertionError: unexpected exception type thrown; expected:<com.myproject.MyCustomException> but was:<java.lang.NullPointerException>

Зависимости Maven:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>4.0.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>4.0.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>4.0.0</version>
    <scope>test</scope>
</dependency>

Дикое предположение, что в вашем тесте нет @ExtendWith(MockitoExtension.class) или используется неправильный @Test (тот, что из JUnit4 вместо JUnit5). Но поскольку вы разместили только частичный фрагмент вместо полного теста, это невозможно узнать.

M. Deinum 20.02.2023 11:34

@M.Deinum Добавлено больше деталей к вопросу.

Michi-2142 20.02.2023 11:43

Я ожидаю, что трассировка стека даст вам четкое представление о том, почему вы получаете NPE.

k314159 20.02.2023 12:00

Я бы начал с обновления Mockito. 4.0.0 немного устарела, я бы по крайней мере попробовал 4.11 или даже переключился на релизы 5.x. Это еще не полный тестовый пример, так как я ожидаю некоторого дополнительного импорта.

M. Deinum 20.02.2023 12:07

Ваш код должен перехватывать NPE и повторно выдавать его как ваш тип исключения. Либо так, либо если вы получите NPE в своей службе, пусть он выдаст ваш тип исключения.

Dale 20.02.2023 12:11

@M.Deinum M.Deinum Обновление до 4.11 дает мне подробный журнал, спасибо!

Michi-2142 20.02.2023 13:00

Почему @Spy? Вы не следите за звонками и не перехватываете звонки

knittl 20.02.2023 13:53
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
7
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

проблема в аннотации @InjectMocks и @Spy. Использование их вместе не имеет смысла (как обсуждалось в этом посте stackoverflow). Создание класса вручную решает проблему NullPointerException, и тест проходит успешно

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

import static 
org.junit.jupiter.api.Assertions.assertThrows;

@ExtendWith(MockitoExtension.class)
public class MyServiceTest {
   MyService myServiceToTest;

   @Test
   public void invoke_ShouldThrow_MyCustomException() {
      MyService myServiceToTest = new MyService();
      assertThrows(MyCustomException.class, () -> {
        myServiceToTest.invoke(null);
      });
   }
}  

Вам даже не нужен @ExtendWith с этим (это фактически замедлит скорость вашего теста, поскольку он будет сканировать класс на наличие аннотаций mockito).

M. Deinum 20.02.2023 13:31

Другие вопросы по теме