In the following configuration bean example,
@Configuration
public class LazyConfig
{
@Bean
@Lazy
public SomeBean someBean(final DependencyBean dependencyBean)
{
return new SomeBean(dependencyBean);
}
}
I expected the following test using ApplicationContextRunner
should be working, but it fails:
class LazyConfigTest
{
ApplicationContextRunner runner = new ApplicationContextRunner()
.withUserConfiguration(LazyConfig.class);
@Test
void testNoLazyIsLoaded()
{
runner.run(context -> {
org.assertj.core.api.Assertions.assertThat(context).getBeanNames(SomeBean.class).isEmpty();
// > Expecting empty but was: ["someBean"]
org.assertj.core.api.Assertions.assertThat(context).doesNotHaveBean(SomeBean.class);
// > Expecting not to have, but found: <["someBean"]>
});
}
}
But then trying to get the bean itself fails for depedant,
context.getBean(SomeBean.class);
// > Error creating bean with name 'someBean' defined in org.lucasvc.lazy.config.LazyConfig: Unsatisfied dependency expressed through method 'someBean' parameter 0: No qualifying bean of type 'org.lucasvc.lazy.DependencyBean' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
It is expected that there is such "beans" in the context, even annotated method with Lazy
?
How should be the best way to test the Lazy
behavior?
You have to consider how @Lazy
beans work in Spring. If I have a class LazyBeanA that is marked as @Lazy
, and I declare a class NotLazyB that autowires LazyBeanA does that negate LazyBeanA's laziness? No, it doesn't. But how does it construct NotLazyB if it's "eager" if not all properties can be satisfied? It can't satisfy the LazyBeanA autowire because it's lazy. Well, Spring gets around that by instantiating a proxy that sits in front of LazyBeanA. LazyBeanA isn't constructed, but the Proxy is. The proxy is a "stunt" bean. It's stands in for LazyBeanA until you invoke a method on it. At that point it constructs LazyBeanA, populates it's dependencies, and invokes the method.
So there is something registered under that bean's class/id. It's just the stunt bean.