I attempting to instantiate Spring boot applicationContext and dynamically register beans within a test class to so it can acts as the real main class client's behavior. But I run the code (sample below) somehow the bean I register gets lost when it reaches to ClassFromMainCode.isBean method.
Testing class
@SpringBootTest(
classes = { ClassFromMainCode.class },
webEnvironment = Spring.WebEnvironment.NONE
)
@Configuration
@ContextConfiguration
public class SampleTestClass {
private ConfigurableApplicationContext applicationContext;
@Test
public void testCase1() {
beanName = "abc";
Class beanClass = String.class;
registerSpringBean(beanName, beanClass);
//returns False
new ClassFromMainCode().isBean(beanName);
//returns True
this.applicationContext.containsBean(beanName);
}
private void registerSpringBean(String beanName, Class<?> beanClass) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext;
registry.registerBeanDefinition(beanName, new TestGenericBeanDefinition(beanClass));
applicationContext.refresh();
}
public SampleTestClass() {
applicationContext = new AnnotationConfigApplicationContext();
}
}
Main class
@Component
public class ClassFromMainCode {
@Autowired
private ApplicationContext applicationContext;
boolean isBean(String beanName) {
return applicationContext.containsBean(beanName);
}
}
I expected the new ClassFromMainCode().isBean(beanName); to return true instead of false. I am wondering how I can appropriately define Spring applicationContext and register beans in a way that is presevered to reach to main code?
You are having two different application contexts. (1) created by you in the constructor of the test class. You use this one in your test method to register a bean called "abc". (2) created by Spring as a result of your annotation
@SpringBootTeston your test class. This context only contains beans declared in the classes specified in theclassesproperty. You have only one class declared in that propertyClassFromMainCodewhich doesn't contain any beans.Fix
Instead of creating your own application context in the constructor, use the one created by Spring for you. Autowire it in your test class and use that one instead.
Delete the constructor.