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

如何在Spring测试上下文注入@Repository与多个@Service

需求与问题

我基于Spring开发REST接口,要单独测试包含mapper、repository和验证逻辑的业务层,做不含REST部分的胖集成测试/系统测试。我拒绝使用Mock,因为Mock的行为是自定义的,无法反映待测试代码的真实情况,可能和业务代码一样存在bug;只在无法通过输入触发行为时才考虑Mock。

目前遇到的问题是测试中组件组装困难:现有示例要么是仅聚焦repository的@DataJpaTest,要么是Controller/系统测试中Mock底层逻辑。我需要能灵活组合测试组件(可选择Mock或不Mock部分组件),但Spring测试加载的上下文不全,导致无法找到所需组件,运行测试时报错。


业务代码

// 业务逻辑实现类
public class IAMBusinessLogicImplementation implements IAMBusinessLogicInterface {

    private final UserRepositoryInterface _userRepository;
    private final UserMapperInterface _userMappers;
    private final IAMValidatorInterface _validator;

    public IAMBusinessLogicImplementation(
        @NonNull UserRepositoryInterface _userRepository,
        @NonNull UserMapperInterface _userMappers,
        @NonNull IAMValidatorInterface _validator) {
        this._userRepository = _userRepository;
        this._userMappers = _userMappers;
        this._validator = _validator;
    }

    public UserDto createUser(@NonNull UserDto userDto) {
        // 业务逻辑实现
    }
}

// 验证器实现类
public class IAMValidatorImplementation implements IAMValidatorInterface { }

// Mapper实现类
public class UserMapperImplementation implements UserMapperInterface { }

// Repository接口
public interface UserRepositoryInterface extends CrudRepository<User, Long> { }

测试代码

@SpringBootTest(classes = {IAMBusinessLogicImplementation.class})
@EnableJpaRepositories(basePackages = "com.encyclopediagalactica.iam.tests.repository")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@AutoConfigureDataJpa
@EntityScan("com.encyclopediagalactica.iam.entities")
@ComponentScan()
public class IAMBusinessLogicTestsBase {

    @Autowired
    public IAMBusinessLogicInterface _sut;

    @Test
    public void createUser() {
        // Arrange
        UserDto userDto = UserDto.builder()
            .firstName("asd")
            .lastName("dsa")
            .build();

        // Act
        UserDto result = _sut.createUser(userDto);

        // Assert
        assertThat(result).isNotNull();
    }
}

错误日志

2023-04-23T21:28:25.495+02:00 WARN 37577 --- [ main]
o.s.w.c.s.GenericWebApplicationContext : Exception encountered
during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'IAMBusinessLogicImplementation':
Unsatisfied dependency expressed through constructor parameter 0: No
qualifying bean of type
'com.encyclopediagalactica.iam.repositories.UserRepositoryInterface'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations: {}

错误核心:Spring无法找到UserRepositoryInterface类型的Bean,无法满足IAMBusinessLogicImplementation的构造函数依赖。


解决方案

1. 修正Repository扫描路径

@EnableJpaRepositories的basePackages配置错误,应该指向业务代码中Repository所在的包,而非测试包:

@EnableJpaRepositories(basePackages = "com.encyclopediagalactica.iam.repositories")

2. 让业务组件被Spring容器管理

业务逻辑类、验证器、Mapper都需要添加Spring组件注解(@Service、@Component等),否则Spring无法扫描生成Bean:

@Service
public class IAMBusinessLogicImplementation implements IAMBusinessLogicInterface {
    // 原有代码不变
}

@Component
public class IAMValidatorImplementation implements IAMValidatorInterface { }

@Component
public class UserMapperImplementation implements UserMapperInterface { }

3. 优化测试上下文配置

  • 建议去掉@SpringBootTest的classes参数,默认加载带@SpringBootApplication的主配置类,这样能自动扫描所有必要组件,避免遗漏依赖;
  • 去掉不必要的@ComponentScan(),如果需要指定扫描范围,明确写出业务代码的根包:
@SpringBootTest
@EnableJpaRepositories(basePackages = "com.encyclopediagalactica.iam.repositories")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@EntityScan("com.encyclopediagalactica.iam.entities")
public class IAMBusinessLogicTestsBase {
    // 原有测试代码不变
}

4. 按需Mock组件(灵活组合)

如果需要Mock某部分组件(比如外部依赖无法在测试环境运行),用@MockBean替换真实Bean,不影响其他组件的真实实例:

@SpringBootTest
@EnableJpaRepositories(basePackages = "com.encyclopediagalactica.iam.repositories")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@EntityScan("com.encyclopediagalactica.iam.entities")
public class IAMBusinessLogicTestsBase {

    @Autowired
    public IAMBusinessLogicInterface _sut;

    // Mock验证器,保留Repository和Mapper的真实实例
    @MockBean
    private IAMValidatorInterface _validator;

    @Test
    public void createUser() {
        // Arrange
        UserDto userDto = UserDto.builder()
            .firstName("asd")
            .lastName("dsa")
            .build();

        // 定义Mock行为
        Mockito.when(_validator.validateUser(any(UserDto.class))).thenReturn(true);

        // Act
        UserDto result = _sut.createUser(userDto);

        // Assert
        assertThat(result).isNotNull();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 00:00:43