Издевательство над RestTemplate происходит с помощью spring boot 2.x вызывает исключение нулевого указателя

#unit-testing #mockito #spring-boot-test

Вопрос:

Я пишу модульный тест для своего уровня обслуживания, который вызывает серверную службу REST и MongoDB. Но при выполнении моего теста в локальной среде все работает нормально, но когда я упаковываю свое приложение в конвейер CICD во время компиляции, он пытается запускать модульные тесты, при этом получая исключения с нулевым указателем при использовании RestTemplate и MongoTemplate компонентов.

 MyTestService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private MongoTemlate mongoTemplate;

    public String callDBAndBackend() {

        // some business logic
        UpdatedObject mongoDoc = mongoTemplate.updateFirst(updateObject);

        restTemplate.exchange(reqEntity, ResponseObject.class);
        return "Success";
    }
}
 
 @ExtendWith(MockitoExtension.class)
MyTestServiceTest {

    @Mock
    private RestTemplate restTemplate;

    @Mock
    private MongoTemplate mongoTemplate;


    @InjectMocks
    private MyTestService myTestService;

    @Test
    public void testCallDBAndBackend() {

        when(restTemplate.exchange(reqEntity, ResponseObject.class)).thenReturn("Success"); // In this line getting Null pointer. Cant able to inject restTemplate
        when(mongoTemplate.updateFirst(updateObject)).thenReturn("Success"); // In //this line getting Null pointer. Cant able to inject mongoTemplate

    myTestService.callDBAndBackend();

    }
}
 

pom.xml

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
    </parent>

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
    <!--    <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>  -->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
 

При компиляции этого кода я получаю объект RestTemplate и MongoTemplate как null, что вызывает NPL. Если я запущу тот же код из IDE, он будет работать нормально и получит допустимые макетные объекты RestTemplate и MongoTemplate.

Комментарии:

1. Можете ли вы добавить импорт вашего тестового класса? Возможно ли, что вы смешиваете JUnit 4 и JUnit 5 в одном тесте?

Ответ №1:

Вы можете использовать InjectMocks аннотацию к целевому классу MyTestService для вставки издевательских объектов.

Ваше решение должно дать вам НЛП, потому что вы не предоставили издевательские объекты MyTestService

то есть

 @ExtendWith(MockitoExtension.class)
MyTestServiceTest{

@InjectMocks
private MyTestService service;

@Mock
private RestTemplate restTemplate;

@Mock
private MongoTemplate mongoTemplate;

@Test
public void testCallDBAndBackend() {
    // Arrange
    when(restTemplate.exchange(reqEntity,ResponseObject.class))
    .thenReturn("Success");
    when(mongoTemplate.updateFirst(updateObject)).thenReturn("Success");

     // Act
     String actual = service.callDBAndBackend();

     // Assert
     ...
    }
}
 

Комментарии:

1. Я только что обновил свой вопрос аннотацией » @»InjectMock, но все равно получаю ту же проблему. Здесь проблема в том, что я каким-то образом не смог получить конкретные компоненты Spring в моем контексте тестирования во время сборки. То же самое работает нормально, если я выполняю свой код из своей среды разработки. Я подозреваю, что компоненты, зависящие от spring, недоступны для контекста тестирования во время сборки. Такой же код отлично работает с Junit4