SpringBootTest中如何用内部类替换指定测试的Bean?
Spring Boot集成测试Mock LDAP连接池的Bean冲突问题
需求与初始实现
为了在集成测试中避免连接真实LDAP服务,我尝试给LDAPConnectionPool Bean创建Mock实现,编写了如下测试类:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) internal class MyControllerTest{ ... @TestConfiguration internal class LdapConnectionPoolConfig { @Bean @Primary fun ldapConnectionPool(): LDAPConnectionPool { return mockk() } } @Test fun foo() {...}
触发的错误
启动测试调试时,发现内部配置类的方法虽被调用,但生产环境的配置类也被执行,抛出Bean注册冲突错误:
The bean 'ldapConnectionPool', defined in ****.MyControllerTest$LdapConnectionPoolConfig, could not be registered. A bean with that name has already been defined in class path resource [****/LdapConnectionPoolConfig.class] and overriding is disabled.
尝试通过配置开启Bean覆盖:
spring: main: allow-bean-definition-overriding: true
但此时又出现新错误——生产环境的配置类仍被加载,导致依赖注入失败:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ldapConnectionPoolConfig' defined in file [****\LdapConnectionPoolConfig.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name '****.LdapConnectionProperties': Could not bind properties to 'LdapConnectionProperties' : prefix=ldap.connection, ignoreInvalidFields=false, ignoreUnknownFields=true
测试情况补充
- 若使用与生产配置同名同包的顶级配置类,测试可正常运行:
测试类代码:
对应的测试配置类:@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @Import(LdapConnectionPoolConfig::class) class MyControllerTest {@TestConfiguration class LdapConnectionPoolConfig { @Bean fun ldapConnectionPool(): LDAPConnectionPool = mockk() - 但如果将测试配置类改名(比如改为
LdapConnectionPoolConfigAnotherName),则会再次触发上述Bean冲突或依赖注入错误。我更倾向于使用内部类的方式实现Mock配置。
复现规律
已完成最小复现验证:仅当@TestConfiguration标注的测试配置类与生产环境配置类同名同包且Bean名称一致时,测试才能成功;否则Spring会尝试加载生产环境的真实Bean,引发错误。
内容的提问来源于stack exchange,提问作者gstackoverflow
相关产品推荐
相关产品推荐

