
在 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:
// ❌ 危险示例:手动 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 的误用,往往源于混淆了单元测试与集成测试的边界。明确测试目的,才能选对工具。

















