#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