春天尝试在模拟实例中注入@Autowired依赖项

时间:2019-01-31 01:53:02

标签: testing groovy mocking spock spring-test

我有以下课程: com.foo.pkgx:

@Component public class A {}

@Component public class B {
    @Autowired A a;
}

com.foo.pkgy:

@Component public class C {
    @Autowired B b;
}

I.E。依赖关系:C-> B-> A

执行以下spock规范时:

@Configuration
@ComponentScan(basePackages = ["com.foo.pkgy"])
class Config {
    def mockFactory = new DetachedMockFactory()

    @Bean
    B b() {mockFactory.Mock(B)};
}

@ContextConfiguration(classes = Config)
class CSpec extends Specification {

    @Autowired
    C c;

    def "sanity"() {
        expect: c
    }
}

测试未能初始化:

Caused by: org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'c': 
Injection of autowired dependencies failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: 
Could not autowire field: com.foo.pkgx.B com.foo.pkgy.C.b; 
nested exception is org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'b': 
Injection of autowired dependencies failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: 
Could not autowire field: com.foo.pkgx.A com.foo.pkgx.B.a; 
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type [com.foo.pkgx.A] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

我将其读为“试图将A连接到B,但失败了”。我没想到B会被自动装配,因为它被嘲笑了。

有人可以给我一些启示吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

类的模拟是由代码生成库,字节伙伴或cglib-nodep等生成的子类。从Spring的角度来看,这是一个普通的bean。并且一旦实例化了任何bean,然后在某个时候,Spring就会通过各种...BeanPostProcessors来对bean进行“自省”。例如。自动装配由AutowiredAnnotationBeanPostProcessor处理。该后处理器的工作方式是,整个类层次结构中的每个bean都是inspected。因此,您的class B@Autowired字段A在那里,Spring尝试解决这种依赖关系时没有运气。

然而,好消息是,需要禁用每个bean的自动装配功能。最终看起来像Spring团队will introduce it soon

与此同时,您可以模拟A,以便解决B的依赖性。或者,您可以只为组件使用接口,而不是仅使用类。我相信后者是最佳实践