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

Spring Boot中JUnit5测试依赖注入失败的原因及替代注入方案

问题:Spring Boot + JUnit5 测试类依赖注入失败

场景说明

基于Spring Boot、JUnit5和Lombok的项目中,编写了一个简单的工具类:

public class Calculator {
    public int subtract(int a, int b) {
        return a - b;
    }
}

对应的测试类代码如下:

import lombok.AllArgsConstructor;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

@AllArgsConstructor
class CalculatorTest {
    private final Calculator calculator;

    private static final int SUBTRACTION_RESULT = 2;


    @Test
    void subtractTest() {
        int result = calculator.subtract(5, 3);
        assertEquals(result, SUBTRACTION_RESULT);
    }
}

报错信息

运行测试后抛出异常:

org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [final com.udemy.junits.Calculator calculator] in constructor [public com.udemy.junits.CalculatorTest(com.udemy.junits.Calculator)].

已尝试操作

  1. 移除Lombok的@AllArgsConstructor,手动编写构造器,依然报相同错误:
public CalculatorTest(Calculator calculator) {
    this.calculator = calculator;
}
  1. 使用@BeforeAll手动实例化Calculator,测试正常运行:
@BeforeAll
static void init() {
    calculator = new Calculator();
}

疑问

  • 是否因为未启动应用上下文导致无法依赖注入?
  • 能否不通过new Calculator()的方式实现依赖注入?

解答

依赖注入失败的核心原因

没错,你的判断完全正确——JUnit5本身不具备Spring的依赖注入能力,默认情况下不会启动Spring应用上下文。JUnit5只会直接实例化测试类,当测试类构造器需要Calculator参数时,它找不到对应的参数解析器(ParameterResolver)来提供实例,因此抛出异常。

无需手动new的依赖注入方案

有几种可行的方案可以实现依赖注入,不用手动创建实例:

1. 启动完整Spring上下文(最简方案)

给测试类添加@SpringBootTest注解,它会启动完整的Spring应用上下文。同时要确保Calculator被Spring管理(添加@Component注解):

修改Calculator类:

import org.springframework.stereotype.Component;

@Component
public class Calculator {
    public int subtract(int a, int b) {
        return a - b;
    }
}

修改测试类:

import lombok.AllArgsConstructor;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
@AllArgsConstructor
class CalculatorTest {
    private final Calculator calculator;

    private static final int SUBTRACTION_RESULT = 2;

    @Test
    void subtractTest() {
        int result = calculator.subtract(5, 3);
        assertEquals(SUBTRACTION_RESULT, result);
    }
}

2. 启动轻量上下文(按需加载Bean)

如果不想启动完整应用上下文,可以用@ExtendWith(SpringExtension.class)配合@ContextConfiguration,只加载测试需要的Bean配置:

import lombok.AllArgsConstructor;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = CalculatorTest.TestConfig.class)
@AllArgsConstructor
class CalculatorTest {
    private final Calculator calculator;

    private static final int SUBTRACTION_RESULT = 2;

    @Configuration
    static class TestConfig {
        @Bean
        public Calculator calculator() {
            return new Calculator();
        }
    }

    @Test
    void subtractTest() {
        int result = calculator.subtract(5, 3);
        assertEquals(SUBTRACTION_RESULT, result);
    }
}

3. 自定义JUnit5参数解析器

如果只是单纯不想在测试代码里写new,可以自定义一个ParameterResolver来提供Calculator实例,但这种方式本质还是手动创建实例,仅适合有复杂实例化逻辑的场景,一般不推荐用于简单工具类测试。

额外提示

对于Calculator这类无依赖的简单工具类,手动new实例是最轻便的测试方式,无需启动Spring上下文,测试执行速度更快。只有当测试需要依赖Spring容器中的其他Bean(比如Service依赖Repository)时,才需要启动上下文进行依赖注入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:46:22