【问题标题】:JUnit5 SpringBootTest NullPointerException when testing Service测试Service时的JUnit5 SpringBootTest NullPointerException
【发布时间】:2020-01-10 06:36:12
【问题描述】:

我正在关注对服务进行单元测试的教程,并且我正在尝试使用 JUnit5 而不是 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'
}

【问题讨论】:

    标签: junit5 spring-boot-test


    【解决方案1】:

    这看起来像是您试图将集成测试与单元测试混合使用。

    当您使用@SpringBootTest 注释时,Junit5 的SpringExtension 在运行测试之前启动应用程序上下文,并且要在测试中进行模拟,您需要使用@MockBean 注释而不是@Mock@InjectMocks。这是不同的测试范围。

    如我所见,您只需要一个单元测试,就可以删除 SpringBootTest 注释。

    顺便说一句,我认为你在when(courseRepo.... 中因为你any(Course.class) 而获得了NPE 尝试使用isNull()any()(不指定具体类)。

    【讨论】:

    • 谢谢!你的回答奏效了——并把我带到了 any() 的 Mockito 文档,上面写着“自 Mockito 2.1.0 以来,只允许 的非空实例,因此 null 不再是有效值。”
    猜你喜欢
    • 2021-08-24
    • 1970-01-01
    • 2021-01-10
    • 2022-01-17
    • 2017-07-24
    • 2020-08-25
    • 2019-04-23
    • 1970-01-01
    • 2019-09-15
    相关资源
    最近更新 更多