testing - 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 会进行自动装配,因为它被嘲笑了。
有人可以解释一下吗?
谢谢!
解决方案
Mock 类是由代码生成库、byte-buddy 或 cglib-nodep 等生成的子类。从 Spring 的角度来看,它是一个普通的 bean。一旦任何 bean 被实例化,那么在某个时候,Spring 就会通过各种...BeanPostProcessors
. 例如,自动装配由AutowiredAnnotationBeanPostProcessor
. 这个后处理器的工作方式是通过整个类层次结构检查每个 bean。所以你class B
在@Autowired
现场A
,Spring 试图解决这种依赖关系,但没有运气。
然而,好消息是,需要在每个 bean 的基础上禁用自动装配这种功能。并且看起来最终,Spring 团队将很快推出它。
同时,您可以模拟A
,以便B
解决 ' 的依赖关系。或者你可以只为你的组件使用接口,而不是只使用类。我相信后者是最佳实践
推荐阅读
- c++ - 搜索 .csv 文件并返回具有特定字符串 c++ 的所有行
- html - 导航栏菜单中的 HTML/CSS 下拉菜单
- excel - 列表框在vba用户表单中按日期时间排序/过滤?
- macos - 如何在 FreeBSD(和 macOS)中守护 shell 脚本
- oracle - 如何使用 Suitescript 2.0 登录网站?
- java - 如何在纳秒范围内找到 java 数学库函数的确切执行时间?
- javascript - 在 js 承诺中捕获错误
- php - DOMDocument::load():在实体中找不到命名空间默认前缀
- python - 如何在 Python 中执行冒泡排序
- html - 在下拉列表中引入水平滚动?