首页 > 解决方案 > spring 尝试在 Mocked 实例中注入 @Autowired 依赖项

问题描述

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

@Component public class A {}

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

com.foo.pkgy:

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

IE 依赖: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 会进行自动装配,因为它被嘲笑了。

有人可以解释一下吗?

谢谢!

标签: testinggroovymockingspockspring-test

解决方案


Mock 类是由代码生成库、byte-buddy 或 cglib-nodep 等生成的子类。从 Spring 的角度来看,它是一个普通的 bean。一旦任何 bean 被实例化,那么在某个时候,Spring 就会通过各种...BeanPostProcessors. 例如,自动装配由AutowiredAnnotationBeanPostProcessor. 这个后处理器的工作方式是通过整个类层次结构检查每个 bean。所以你class B@Autowired现场A,Spring 试图解决这种依赖关系,但没有运气。

然而,好消息是,需要在每个 bean 的基础上禁用自动装配这种功能。并且看起来最终,Spring 团队将很快推出它

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


推荐阅读