如何在 Spring 测试中正确选择 @Autowired 与 @Mock?

千枫大大_8214

千枫大大_8214

2026-06-14

379人浏览

原创

如何在 Spring 测试中正确选择 @Autowired 与 @Mock?

在 Spring 集成测试(如 @SpringBootTest)中,应优先使用 @Autowired 获取真实 Bean;而 @Mock 适用于单元测试中隔离依赖,但对链式调用(如 WebClient/ WebTestClient)易因未定义行为导致 NPE——此时直接注入真实测试专用组件(如 WebTestClient)更合理、更可靠。

在 spring 集成测试中,应优先使用 @autowired 获取真实 bean;而 @mock 适用于单元测试中隔离依赖,但对链式调用(如 webclient/ webtestclient)易因未定义行为导致 npe——此时直接注入真实测试专用组件(如 webtestclient)更合理、更可靠。

在 Spring 生态的测试实践中,@Autowired 和 @Mock 并非可互换的“备选方案”,而是服务于不同测试层级与目标的核心机制:

✅ @Autowired 适用于集成测试场景
当你使用 @SpringBootTest 或 @WebMvcTest 等启动部分或完整 Spring 上下文的测试时,@Autowired 会从容器中注入真实、已配置、可运行的 Bean。例如:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserControllerIntegrationTest {

    @Autowired
    private WebTestClient webTestClient; // ✅ 正确:注入 Spring 自动配置的测试客户端

    @Test
    void shouldReturnFluxOfIntegers() {
        webTestClient.get()
                .uri("/api/numbers")
                .exchange()
                .expectStatus().isOk()
                .expectBodyList(Integer.class);
    }
}

此处 WebTestClient 是 Spring Boot Test 自动配置的真实测试代理,它不发起真实 HTTP 请求,而是通过模拟服务器(如 MockServer)直接调用 Controller 层,兼具真实性与可控性。

❌ @Mock 不适合替代 WebTestClient
@Mock(配合 @ExtendWith(MockitoExtension.class))创建的是完全空壳对象,所有方法默认返回 null(引用类型)、0(数值)、false(布尔)等“默认值”。对 WebTestClient 这类深度链式 API(.get().uri().exchange()),一旦 .get() 返回 null,后续调用必然触发 NullPointerException:

nexu
nexu

nexu是一款AI智能体工具,免费开源的 OpenClaw 桌面客户端。

下载
// ❌ 危险示例:手动 mock WebTestClient(不推荐)
@Mock
private WebTestClient webTestClient; // → 所有方法返回 null!

@Test
void brokenTest() {
    webTestClient.get() // ← 返回 null!
            .uri("/api/numbers") // ← NPE here!
            .exchange();
}

你遇到的 NPE 正源于此:Mockito 无法自动推断链式调用的返回类型并递归 mock,必须显式 stub 每一层(如 when(mock.get()).thenReturn(mockRequestSpec)),这既繁琐又违背测试简洁性原则。

? 何时该用 @Mock?
仅在纯单元测试(无 Spring 上下文) 中,用于隔离被测类的外部依赖。例如测试一个 Service 类时,mock 其依赖的 Repository:

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @InjectMocks
    private UserService userService;

    @Mock
    private UserRepository userRepository; // ✅ 合理:mock 数据访问层,聚焦业务逻辑

    @Test
    void shouldFindUserById() {
        when(userRepository.findById(1L)).thenReturn(Optional.of(new User("Alice")));
        assertThat(userService.findById(1L)).isPresent();
    }
}

? 关键实践建议:

  • 集成测试(@SpringBootTest / @WebMvcTest)→ 用 @Autowired:信任 Spring 的自动配置,获取开箱即用的测试基础设施(如 WebTestClient, TestRestTemplate, JdbcTemplate)。
  • 单元测试(无 Spring 上下文)→ 用 @Mock + @InjectMocks:严格控制依赖行为,验证单个类的内部逻辑。
  • 绝不 mock 测试专用组件(如 WebTestClient, MockMvc, TestEntityManager):它们本就是为测试设计的轻量级真实实现,mock 它们等于放弃框架提供的测试便利性。
  • 若需拦截 HTTP 行为(如验证请求头、模拟网络错误),请使用 WebTestClient 的 mutateWith() 或 exchange() 后的 expect* 断言,而非 mock。

总之,@Autowired 在测试类中不仅“不愚蠢”,反而是 Spring Boot 测试范式的基石;而 @Mock 的误用,往往源于混淆了单元测试与集成测试的边界。明确测试目的,才能选对工具。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2025.08.06

2411

22

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

2026.01.26

437

25

软件测试常用工具
软件测试常用工具

软件测试常用工具有Selenium、JUnit、Appium、JMeter、LoadRunner、Postman、TestNG、LoadUI、SoapUI、Cucumber和Robot Framework等等。测试人员可以根据具体的测试需求和技术栈选择适合的工具,提高测试效率和准确性 。

2023.10.13

4390

8

java测试工具有哪些
java测试工具有哪些

java测试工具有JUnit、TestNG、Mockito、Selenium、Apache JMeter和Cucumber。php还给大家带来了java有关的教程,欢迎大家前来学习阅读,希望对大家能有所帮助。

2023.10.23

2781

10

Java 单元测试
Java 单元测试

本专题聚焦 Java 在软件测试与持续集成流程中的实战应用,系统讲解 JUnit 单元测试框架、Mock 数据、集成测试、代码覆盖率分析、Maven 测试配置、CI/CD 流水线搭建(Jenkins、GitHub Actions)等关键内容。通过实战案例(如企业级项目自动化测试、持续交付流程搭建),帮助学习者掌握 Java 项目质量保障与自动化交付的完整体系。

2025.10.24

1046

26

FrankenPHP集成Laravel详细教程
FrankenPHP集成Laravel详细教程

本专题提供FrankenPHP集成Laravel的详细配置指南,全面解析运行原理、开发环境搭建、Caddyfile配置、Octane工作模式、数据库连接、队列任务、定时任务和生产环境优化,解决部署过程中常见的报错与兼容性问题。

2026.10.08

40

20

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

2026.09.30

140

10

LLVM RISC-V参数配置教程
LLVM RISC-V参数配置教程

本专题介绍LLVM对RISC-V基础ISA和扩展的支持方式,涵盖RV32、RV64、标准扩展、实验性扩展、厂商扩展、-menable-experimental-extensions和版本差异。

2026.09.30

140

14

LLVM IR中间表示入门指南
LLVM IR中间表示入门指南

本专题整理LLVM IR的核心概念,包括中间表示作用、模块结构、函数、基本块、SSA形式、类型系统和常见语法,帮助新手理解LLVM编译流程中的关键层。

2026.09.30

100

12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Apifox官方手册
Apifox官方手册

共0课时 | 0人学习

apipost极速入门
apipost极速入门

共6课时 | 0.6万人学习