【问题标题】:Spring Test + Mockito.mock - Spring fails because it tries to load the mocked bean @Autowired dependenciesSpring Test + Mockito.mock - Spring 失败,因为它尝试加载模拟的 bean @Autowired 依赖项
【发布时间】:2016-03-07 12:46:01
【问题描述】:

我无法找出以下简单场景失败的原因:我有一个带有过滤器的 Spring 应用程序,该过滤器从应用程序上下文加载 Spring bean:

public class MyFilter implements Filter{

    private IPermissionService permissionService;

    public void init(FilterConfig filterConfig) throws ServletException {
        WebApplicationContext ac = null;
        try{
            ac = WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext());
            permissionService = ac.getBean(PermissionServiceImpl.class);

PermissionServiceImpl 有一个 @Autowired 属性 dataSource 所以在我的 TestNG 测试中,我在 Spring applicationContext 中模拟它:

@Configuration
public class MyFilterSpringTestConfig{

    @Bean
    public IPermissionService permissionService(){
        return Mockito.mock(PermissionServiceImpl.class);
    }

我的测试:

@Test
@WebAppConfiguration
@ContextConfiguration(classes=MyFilterSpringTestConfig.class)
public class MyFilterSpringTest extends BaseSpringFilterTest{

   ...

问题是在 Spring 初始化时我收到一个异常,抱怨 PermissionServiceImpl 的 dataSource 依赖不满足。既然我用模拟包裹它,为什么它仍然失败?我该如何解决?

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] 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), @org.springframework.beans.factory.annotation.Qualifier(value=myDataSource)}

【问题讨论】:

  • 不要模拟类,模拟接口。如果您创建一个类的模拟,它仍然是该类的一个实例,其中包含所有变量和注释,而这些变量和注释仍然会被扫描。所以你应该模拟接口(也应该像现在这样对接口而不是具体的类进行编程)。
  • 模拟界面是对的。但是在这种情况下,将有两个过滤器:用于 PermissionServiceImpl 的 Filter1 和用于 PermissionServiceImpl2 的 Filter2。开发人员必须在 web.xml 中定义他们喜欢的过滤器,并根据过滤器为 PermissionServiceImpl 或 PermissionServiceImpl2 导入匹配的 spring 上下文。在过滤器中使用 permissionService = ac.getBean(PermissionServiceImpl.class); 有助于确保他们没有导入错误的 xml
  • 那么接口有什么用... 使用profiles或者其他的接线方式或者创建2个接口,为什么需要2个同一个接口的实现和2个过滤器呢?该设置首先似乎有问题。感觉就像您正在尝试构建某些东西,而您一开始就不应该这样做......
  • 是的,我知道这很乱。我们必须支持一些与问题无关的遗留内容(过滤器还支持非弹簧初始化等)。我会忘记模拟实现(并依赖于阅读文档的开发人员)。无论如何,如果您对模拟实现类的不可能有疑问,我会接受答案。谢谢!
  • 你可以完美地模拟类,但是 Springs 机制仍然会检测到注解,因为它们仍然是包含所有信息的类的实例。要么不使用自动连线并删除注释(然后什么都不会扫描),要么使用接口。

标签: spring mockito testng spring-test


【解决方案1】:

当使用 Mockito(或任何其他模拟框架)模拟一个类时,该类仍然是原始类的一个实例。随之而来的是它还包含所有注释和类信息。

因此,当您创建该类的模拟时,它仍会检测其上的所有注释并尝试完全填充。 IE。 @Autowire 其他实例。

要么不使用自动连接,要么不模拟类而是模拟接口(不包含该信息)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-24
    • 2019-06-24
    • 2019-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多