Java 在Spring集成测试期间刷新/重建特定bean
我们现有的Spring Boot集成设置使用Java 在Spring集成测试期间刷新/重建特定bean,java,spring,spring-boot,junit,integration-testing,Java,Spring,Spring Boot,Junit,Integration Testing,我们现有的Spring Boot集成设置使用@DirtiesContext在不同的测试方法之间重建整个bean池 这相当缓慢,因此我们开始使用可以“刷新”或内部拆除/重建的bean,而无需重新创建实例 问题是只有一些bean支持这一点。如果我们控制UsersBean,我们可以实现UsersBean.refresh()方法,并在@After方法中调用它 但是,如果我们现有的bean/类不支持刷新,或者我们不进行控制,那么我们如何有条件地指示某些bean需要在特定测试之后被弄脏/重建呢 或者更简洁地
@DirtiesContext
在不同的测试方法之间重建整个bean池
这相当缓慢,因此我们开始使用可以“刷新”或内部拆除/重建的bean,而无需重新创建实例
问题是只有一些bean支持这一点。如果我们控制UsersBean
,我们可以实现UsersBean.refresh()
方法,并在@After
方法中调用它
但是,如果我们现有的bean/类不支持刷新,或者我们不进行控制,那么我们如何有条件地指示某些bean需要在特定测试之后被弄脏/重建呢
或者更简洁地说:有没有一种方法可以在测试方法结束时将bean池的一部分标记为脏的,以便重新构建?看起来这是可能的,至少在Spring引导环境中是可能的。
ApplicationContext
实现有一个功能,可以通过重新注册
这甚至可以通过级联来删除包含对正在删除的bean的引用的bean(可以在中看到它的实现)
例如,如果Bean1
被Bean2
引用:
@Component
public class Bean1 {
}
@Component
public class Bean2 {
@Autowired
public Bean1 bean1;
}
然后,测试可以从上下文中删除bean1
,也可以查看bean2
替换:
@RunWith(SpringRunner.class)
public class BeanRemovalTest implements ApplicationContextAware {
@Autowired
private Bean1 bean1;
@Autowired
private Bean2 bean2;
private ApplicationContext applicationContext;
@Test
public void test1() throws Exception {
System.out.println("test1():");
System.out.println(" bean1=" + bean1);
System.out.println(" bean2.bean1=" + bean2.bean1);
resetBean("bean1");
}
@Test
public void test2() throws Exception {
System.out.println("test2():");
System.out.println(" bean1=" + bean1);
System.out.println(" bean2.bean1=" + bean2.bean1);
}
private void resetBean(String beanName) {
GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext;
BeanDefinition bd = genericApplicationContext
.getBeanDefinition(beanName);
genericApplicationContext.removeBeanDefinition("bean1");
genericApplicationContext.registerBeanDefinition("bean1", bd);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
}
这显示了两个被替换的bean实例:
test1():
bean1=hello.so.Bean1@61d6015a
bean2.bean1=hello.so.Bean1@61d6015a
test2():
bean1=hello.so.Bean1@2e570ded
bean2.bean1=hello.so.Bean1@2e570ded
(如果resetBean(“bean1”)
被注释掉,那么它在两次循环中都是相同的实例)
肯定会有一些边不起作用-例如,如果另一个bean持有从
ApplicationContext.getBean()获取的引用,谢谢,这看起来很完美。我会测试一下,19小时后我可以给你奖金。