You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot GraphQL测试上下文为空,测试用例无法执行

问题描述

我正在使用Spring Boot Test上下文、GraphQL测试与JUnit Jupiter框架测试GraphQL API端点,目标是验证从GraphQL获取数据的接口。但出现上下文加载后为空的问题,导致测试用例无法执行。以下是项目的pom文件与测试代码:

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.espark.adarsh</groupId>
    <artifactId>sspringboot-graphql-crud-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-graphql-crud-example</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-graphql</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.graphql</groupId>
            <artifactId>spring-graphql-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

测试文件

package com.espark.adarsh;
import com.espark.adarsh.entity.Employee;
import com.espark.adarsh.respository.EmployeeRepository;
import com.espark.adarsh.service.EmployeeService;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.graphql.GraphQlTest;
import org.springframework.context.annotation.Import;
import org.springframework.graphql.test.tester.GraphQlTester;
import javax.annotation.PostConstruct;

@GraphQlTest
@Import({EmployeeService.class, EmployeeRepository.class})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class EmployeeControllerTest {

    @Autowired
    EmployeeRepository employeeRepository;

    @Autowired
    EmployeeService employeeService;

    @Autowired
    GraphQlTester graphQlTester;

    @PostConstruct
    void init(){
        employeeService.setEmployeeRepository(employeeRepository);
    }

    @Test
    @Order(1)
    void testGetAllEmployee(){
        String document="""
                 query{
                   getAllEmployee{
                     id
                     firstName
                     lastName
                   }
                 }
                """;
        graphQlTester.document(document)
                .execute()
                .path("getAllEmployee")
                .entityList(Employee.class)
                .hasSize(4);
    }
}

问题分析与解决方案

核心问题

@GraphQlTest是切片测试注解,默认仅加载GraphQL相关组件(如控制器、解析器),不会自动初始化Spring Data JPA的数据源、EntityManager等上下文。直接@ImportRepository和Service会导致依赖的JPA组件未被加载,最终出现空指针或上下文为空的问题。

修复方案

提供两种适配不同测试场景的方案:

方案一:完整上下文测试(适合真实数据库交互)

如果需要验证端到端的数据库查询逻辑,用@SpringBootTest替代@GraphQlTest,它会加载完整的Spring应用上下文,同时自动配置GraphQlTester:

@SpringBootTest
@AutoConfigureGraphQlTester
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class EmployeeControllerTest {

    @Autowired
    EmployeeRepository employeeRepository;

    @Autowired
    EmployeeService employeeService;

    @Autowired
    GraphQlTester graphQlTester;

    // 每个测试前初始化测试数据,避免测试污染
    @BeforeEach
    void init(){
        employeeRepository.deleteAll();
        employeeRepository.saveAll(Arrays.asList(
            new Employee(null, "Adarsh", "Kumar"),
            new Employee(null, "John", "Doe"),
            new Employee(null, "Jane", "Smith"),
            new Employee(null, "Mike", "Wilson")
        ));
    }

    @Test
    @Order(1)
    void testGetAllEmployee(){
        String document="""
                 query{
                   getAllEmployee{
                     id
                     firstName
                     lastName
                   }
                 }
                """;
        graphQlTester.document(document)
                .execute()
                .path("getAllEmployee")
                .entityList(Employee.class)
                .hasSize(4);
    }
}

方案二:Mock依赖测试(仅验证GraphQL解析逻辑)

如果只需要验证GraphQL接口的解析逻辑,不需要真实数据库交互,用@MockBean模拟业务层依赖:

@GraphQlTest(EmployeeController.class) // 指定要测试的GraphQL控制器/解析器
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class EmployeeControllerTest {

    @Autowired
    GraphQlTester graphQlTester;

    @MockBean
    EmployeeService employeeService;

    @BeforeEach
    void init(){
        // 模拟Service返回值
        when(employeeService.getAllEmployee()).thenReturn(Arrays.asList(
            new Employee(1L, "Adarsh", "Kumar"),
            new Employee(2L, "John", "Doe"),
            new Employee(3L, "Jane", "Smith"),
            new Employee(4L, "Mike", "Wilson")
        ));
    }

    @Test
    @Order(1)
    void testGetAllEmployee(){
        String document="""
                 query{
                   getAllEmployee{
                     id
                     firstName
                     lastName
                   }
                 }
                """;
        graphQlTester.document(document)
                .execute()
                .path("getAllEmployee")
                .entityList(Employee.class)
                .hasSize(4);
    }
}

额外优化建议

  1. 替换手动注入方式:在EmployeeService中使用构造函数注入,避免手动调用setEmployeeRepository:
@Service
@RequiredArgsConstructor
public class EmployeeService {
    private final EmployeeRepository employeeRepository;

    // 业务方法实现...
}
  1. 用@BeforeEach替代@PostConstruct:确保每个测试方法执行前都能重置数据,避免测试用例之间的污染。

内容的提问来源于stack exchange,提问作者Adarsh Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 07:37:59