注册FakeDbService时如何阻止父类DbService Bean注册以测试UserService
解决Spring测试中DbService与FakeDbService冲突的问题
针对你遇到的无法阻止Spring注册DbService父类、且不能修改DbService和DbUtil源码的情况,这里提供三种可行的解决方案:
方案1:使用@Primary注解+组件扫描排除父类
如果DbService是通过Spring组件扫描自动注册的,可以通过以下方式确保容器只存在FakeDbService:
- 修改FakeDbService,指定Bean名称为
dbService并标记@Primary:
@Service("dbService") @Primary class FakeDbService extends DbService { @Override public SqlSessionTemplate getSqlSessionTemplate() { // 实现模拟逻辑,比如返回Mock对象 return Mockito.mock(SqlSessionTemplate.class); } }
- 在测试配置中排除DbService的自动扫描:
@Configuration @ComponentScan(basePackages = "你的基础包路径", excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = DbService.class) }) @Import(FakeDbService.class) class TestConfiguration { }
方案2:手动注册FakeDbService并禁用父类注册
直接在测试配置中手动定义名为dbService的Bean,同时排除父类DbService的自动注册:
@Configuration @ComponentScan(basePackages = "你的基础包路径", excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = DbService.class) }) class TestConfiguration { @Bean("dbService") public FakeDbService fakeDbService() { return new FakeDbService(); } @Bean public UserService userService() { return new UserService(); } }
这样Spring容器中只会存在FakeDbService实例,DbUtil通过名称获取时会直接拿到它。
方案3:反射赋值DbUtil的静态字段(最简便)
由于DbUtil中的dbService是静态字段,且仅在为null时才从Spring获取,可在测试前直接通过反射赋值,绕开Spring的Bean注册逻辑:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = TestConfiguration.class) public class Test { @Autowired private UserService userService; @Before public void setUp() throws NoSuchFieldException, IllegalAccessException { Field dbServiceField = DbUtil.class.getDeclaredField("dbService"); dbServiceField.setAccessible(true); // 直接注入FakeDbService实例 dbServiceField.set(null, new FakeDbService()); } @Test public void userServiceTest() { userService.getUser(); } }
如果FakeDbService需要Spring管理的依赖,可先让Spring实例化它再注入:
@Autowired private FakeDbService fakeDbService; @Before public void setUp() throws NoSuchFieldException, IllegalAccessException { Field dbServiceField = DbUtil.class.getDeclaredField("dbService"); dbServiceField.setAccessible(true); dbServiceField.set(null, fakeDbService); }
内容的提问来源于stack exchange,提问作者namyulbae
相关产品推荐
相关产品推荐

