测试服务时JUnit5 SpringBootTest NullPointerException
JUnit5 SpringBootTest NullPointerException when testing Service
我正在学习对服务进行单元测试的教程,我正在尝试使用 JUnit5 而不是 JUnit4(教程使用的是 JUnit4)。当我完全按照 JUnit4 的教程进行测试时,测试工作正常,但我得到了 JUnit5 的 NullPointerException。
存储库:
public interface CourseRepo extends CrudRepository<Course, Long> {}
服务:
@Service
public class CourseService {
private final CourseRepo courseRepo;
public CourseService(CourseRepo courseRepo) {
this.courseRepo = courseRepo;
}
public Course save(Course course) {
Course newCourse = courseRepo.save(course);
return newCourse;
}
}
测试:
package com.elovell.blackboard.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import com.elovell.blackboard.domain.Course;
import com.elovell.blackboard.repository.CourseRepo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@ExtendWith(MockitoExtension.class)
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
public class CourseServiceTest {
@Mock
public CourseRepo courseRepo;
@InjectMocks
public CourseService courseService;
@BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testSaveCourse() {
Course mockCourse = new Course();
mockCourse.setPk1(1L);
mockCourse.setCourseId("ENGL101");
when(courseRepo.save(any(Course.class))).thenReturn(mockCourse);
// save(null) should still return mockCourse
Course newCourse = courseService.save(null);
assertEquals("ENGL101", newCourse.getCourseId());
}
}
这是异常的前几行:
java.lang.NullPointerException
at com.elovell.blackboard.service.CourseServiceTest.testSaveCourse(CourseServiceTest.java:44)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
我的构建文件的测试和依赖部分:
test {
useJUnitPlatform {
includeEngines 'junit-jupiter'
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation("org.junit.jupiter:junit-jupiter-api:5.5.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.1.0")
testCompile 'org.mockito:mockito-junit-jupiter:2.23.4'
}
您似乎在尝试将集成测试与单元测试混合使用。
当您使用 @SpringBootTest
注释时,Junit5 的 SpringExtension
在 运行 您的测试之前启动应用程序上下文,并且要在测试中进行模拟,您需要使用 @MockBean
注释而不是 @Mock
& @InjectMocks
。这是不同范围的测试。
如我所见,您只需要一个单元测试,您可以删除 SpringBootTest
注释。
顺便说一下,我认为你在 when(courseRepo....
中 any(Course.class)
获得了 NPE
尝试使用 isNull()
或 any()
(没有指定具体 class)。
我正在学习对服务进行单元测试的教程,我正在尝试使用 JUnit5 而不是 JUnit4(教程使用的是 JUnit4)。当我完全按照 JUnit4 的教程进行测试时,测试工作正常,但我得到了 JUnit5 的 NullPointerException。
存储库:
public interface CourseRepo extends CrudRepository<Course, Long> {}
服务:
@Service
public class CourseService {
private final CourseRepo courseRepo;
public CourseService(CourseRepo courseRepo) {
this.courseRepo = courseRepo;
}
public Course save(Course course) {
Course newCourse = courseRepo.save(course);
return newCourse;
}
}
测试:
package com.elovell.blackboard.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import com.elovell.blackboard.domain.Course;
import com.elovell.blackboard.repository.CourseRepo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@ExtendWith(MockitoExtension.class)
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
public class CourseServiceTest {
@Mock
public CourseRepo courseRepo;
@InjectMocks
public CourseService courseService;
@BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testSaveCourse() {
Course mockCourse = new Course();
mockCourse.setPk1(1L);
mockCourse.setCourseId("ENGL101");
when(courseRepo.save(any(Course.class))).thenReturn(mockCourse);
// save(null) should still return mockCourse
Course newCourse = courseService.save(null);
assertEquals("ENGL101", newCourse.getCourseId());
}
}
这是异常的前几行:
java.lang.NullPointerException
at com.elovell.blackboard.service.CourseServiceTest.testSaveCourse(CourseServiceTest.java:44)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
我的构建文件的测试和依赖部分:
test {
useJUnitPlatform {
includeEngines 'junit-jupiter'
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation("org.junit.jupiter:junit-jupiter-api:5.5.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.1.0")
testCompile 'org.mockito:mockito-junit-jupiter:2.23.4'
}
您似乎在尝试将集成测试与单元测试混合使用。
当您使用 @SpringBootTest
注释时,Junit5 的 SpringExtension
在 运行 您的测试之前启动应用程序上下文,并且要在测试中进行模拟,您需要使用 @MockBean
注释而不是 @Mock
& @InjectMocks
。这是不同范围的测试。
如我所见,您只需要一个单元测试,您可以删除 SpringBootTest
注释。
顺便说一下,我认为你在 when(courseRepo....
中 any(Course.class)
获得了 NPE
尝试使用 isNull()
或 any()
(没有指定具体 class)。