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

Spring Boot控制器测试中MockMvc始终为null的问题求助

问题分析与解决方案

最关键的问题是测试类注解冲突,直接导致MockMvc无法被正确注入:

你同时用了@WebMvcTest和@SpringBootTest,这俩注解根本不能一起用:

  • @WebMvcTest是专门测控制器的切片测试,只会初始化Spring MVC相关的组件,而且已经自动配置了MockMvc。
  • @SpringBootTest是启动整个Spring上下文的全量测试,一般用来做集成测试。
    俩注解混着用会让Spring容器初始化乱套,@Autowired的MockMvc自然就成null了。

另外,@ExtendWith(MockitoExtension.class)在Spring Boot 2.2之后完全没必要加,@WebMvcTest已经自带Mockito支持;@AutoConfigureMockMvc也是多余的,@WebMvcTest已经帮你配好了MockMvc。


除此之外,代码里还有几个必须改的小问题:

1. 测试方法里的变量错误

你把ResultActions类型的变量写成了Response,而且变量名大小写还不一致,直接会编译报错:

// 错误写法
Response ResultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/books/list"));
response.andExpect(MockMvcResultMatchers.status().isOk());

// 修正后
ResultActions response = mockMvc.perform(MockMvcRequestBuilders.get("/api/books/list"));
response.andExpect(MockMvcResultMatchers.status().isOk());

2. 控制器方法的访问修饰符错了

BookController里的listBooks方法是private的,Spring MVC根本没法识别这个接口,必须改成public:

// 错误写法
private ResponseEntity<Object> listBooks(){...}

// 修正后
public ResponseEntity<Object> listBooks(){...}

3. POM依赖版本混乱

你的pom里parent是Spring Boot 2.1.0,但spring-boot-starter-web却用了3.0.0,这俩版本差了好几个大版本,3.0.0要求Java 17,但你配的是Java 11,肯定会出各种依赖冲突。而且junit-jupiter-engine和mockito-junit-jupiter完全没必要单独加,spring-boot-starter-test已经包含了这些依赖,手动加版本反而会搞出冲突。

给你改好的pom,用支持Java 11的Spring Boot 2.7.x稳定版本:

<?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.15</version>
        <relativePath/>
    </parent>
    <groupId>com.tdd</groupId>
    <artifactId>exemplo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>TDD Exemplo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

最后给你修正后的测试类,别忘了用@MockBean模拟BookService,因为@WebMvcTest不会初始化业务层的Bean,不模拟的话控制器构造注入会失败:

@WebMvcTest(BookController.class)
public class TestControlBook {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private BookService bookService;

    @Test
    public void testListBooks() throws Exception{
        // 模拟业务层返回空列表,避免空指针
        when(bookService.listBooks()).thenReturn(Collections.emptyList());
        
        ResultActions response = mockMvc.perform(MockMvcRequestBuilders.get("/api/books/list"));
        response.andExpect(MockMvcResultMatchers.status().isOk());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:45:13