Nossa configuração existente de integração Primavera Bota estava usando @DirtiesContext
para reconstruir toda a piscina de feijão-nos entre diferentes métodos de ensaio.
Este foi bastante lento, e assim começamos a trabalhar com grãos que poderiam ser "refrescado" ou derrubadas / reconstruir internamente , sem re-criação da instância.
O problema é que apenas alguns grãos apoiar esta. Se nós controlamos UsersBean
, podemos implementar um UsersBean.refresh()
método e chamar-lo em nosso @After
método.
Mas se temos feijão / classes que não suportam refrescante, ou nós não controlamos, como podemos existente condicionalmente indicam que certos grãos precisam ser sujou / reconstruído após um teste específico?
Ou de forma mais sucinta: Existe uma maneira de marcar tão sujo a subseção da sua piscina de feijão, para a reconstrução, no final de um método de teste?
Parece que isso é possível, pelo menos dentro de um ambiente de Primavera de inicialização. A ApplicationContext
aplicação tem um GenericApplicationContext que tem a capacidade de removeBeanDefinition () , que pode então ser re-registrado via registerBeanDefinition () .
Este mesmo cascatas através de feijão remover essa detêm uma referência para o feijão que está sendo removido (a implementação deste pode ser visto na DefaultSingletonBeanRegistry.destroyBean () ).
Por exemplo, se Bean1
é referenciado por Bean2
:
@Component
public class Bean1 {
}
@Component
public class Bean2 {
@Autowired
public Bean1 bean1;
}
Em seguida, um teste pode remover bean1
a partir do contexto, e veja bean2
substituído, bem como:
@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;
}
}
Isto demonstra que ambos os exemplos de feijão ser substituído:
test1():
bean1=hello.so.Bean1@61d6015a
bean2.bean1=hello.so.Bean1@61d6015a
test2():
bean1=hello.so.Bean1@2e570ded
bean2.bean1=hello.so.Bean1@2e570ded
(Se o resetBean("bean1")
está comentada, é a mesma instância ambas as vezes e volta).
Não são obrigados a ter arestas onde este não funciona para fora - por exemplo, se um outro feijão está agarrada uma referência obtido a partir de ApplicationContext.getBean()
.