gpt4 book ai didi

java - 在 Spring 集成测试期间刷新/重建特定 beans

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:31:56 24 4
gpt4 key购买 nike

我们现有的 Spring Boot 集成设置使用 @DirtiesContext 在不同的测试方法之间重建整个 bean 池。

这相当慢,因此我们开始使用可以“刷新”或拆除/重建内部而无需重新创建实例的 bean。

问题 是只有一些bean 支持这个。如果我们控制 UsersBean,我们可以实现一个 UsersBean.refresh() 方法并在我们的 @After 方法中调用它。

但是如果我们现有的 beans/classes 不支持刷新,或者我们不控制,我们如何有条件地指示某些 bean 在特定测试后需要被弄脏/重建?

或更简洁:有没有一种方法可以在测试方法结束时将 bean 池的 子部分 标记为脏,以便重建?

最佳答案

看起来这是可能的,至少在 Spring Boot 环境中是这样。 ApplicationContext 实现有一个 GenericApplicationContext它有能力removeBeanDefinition() , 然后可以通过 registerBeanDefinition() 重新注册.

这甚至通过级联来删除持有对被删除的 bean 的引用的 beans(可以在 DefaultSingletonBeanRegistry.destroyBean() 中看到它的实现)。

例如,如果 Bean1Bean2 引用:

@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() 获得的引用。

关于java - 在 Spring 集成测试期间刷新/重建特定 beans,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53213121/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com