【问题标题】:issue mocking spring jdbctemplate with @Autowired使用@Autowired 模拟spring jdbctemplate 问题
【发布时间】:2011-10-28 13:12:42
【问题描述】:

我使用 mockito 作为模拟对象库。我正在对 DAO 进行单元测试。

DAO 期望 JdbcTemplate 通过@Autowired 注入。因此,DAO 中没有单元测试可以调用的 JDBC 模板的 setter 方法。

我有以下测试 spring 应用程序上下文:

<b:beans 
    xmlns:b="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
         http://www.springframework.org/schema/util
         http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <context:annotation-config />

    <b:bean id="mockito" class="org.mockito.Mockito" />
    <b:bean 
        id="mockJdbcTemplate"
        factory-bean="mockito"
        factory-method="mock">
        <b:constructor-arg value="org.springframework.jdbc.core.JdbcTemplate"/>
    </b:bean>
</b:beans>

我期待在测试执行时,sp​​ring 将创建模拟 jdbctemplate 实例并将其自动连接到 DAO。

但这并没有发生 - 相反,我只是得到以下异常:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.springframework.jdbc.core.JdbcTemplate] 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)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:920)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:789)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
    ... 42 more

以前有人用这种方法成功过吗?

谢谢。

【问题讨论】:

  • 我看不到模拟 JdbcTemplate 的意义。通过模拟 JdbcTemplate 来测试 DAO 有什么意义?你的测试将测试什么?
  • 好吧,我们有一个单独的 DAO 层项目,这是唯一一个代码覆盖率为 0% 的项目,因为我们跳过了为 DAO 编写单元测试,因为大多数方法体都是一个内衬(this.jdbcTemplate .query 或 update) - 但是在外部审计期间,这个(没有测试覆盖)被选中,所以我正在编写单元测试来勾选复选框......
  • 我认为这个DAO项目应该使用集成测试,而不是单元测试。因此,您应该创建一个测试数据库并检查 DAO 方法是否产生正确的结果。另外,看看 DbUnit。
  • 由于各种原因(缺少 Sybase ASE 查询语法支持),我无法使用嵌入式数据库。使用嵌入式数据库进行测试也不是真正的测试...使用独立的测试数据库会减慢测试速度执行……我们有 7 名开发人员和一台 CI 服务器……所以测试不会孤立地执行……
  • 所以实际上测试根本不会测试任何东西,只是用来人为地增加覆盖率。对不起,但这真的很愚蠢。您不妨使用真正的 JdbcTemplate 并捕获并忽略测试中的任何异常。

标签: java spring


【解决方案1】:

我认为问题在于返回泛型类型的工厂方法mock。擦除后spring无法扣除对象类型,尝试通过class属性提供明确的对象类型。

public MockitoMockFactoryBean implements FactoryBean<?>
{
    private Class<?> objectType;

    @Override public Object getObject()
    {
        return Mockito.mock(objectType);
    }
    public void setObjectType(Class<?> objectType)
    {
        this.objectType=objectType;
    }
    @Override public Class<?> getObjectType()
    {
        return objectType;
    }
}

【讨论】:

  • 您好 Kan:我尝试指定类属性 - 无效(但没有其他错误)。
  • 哦,对了如果存在“factory-bean”属性,则不使用“class”属性。然后,除了创建一个FactoryBean 实现之外,我没有看到任何选项,它将通过getObjectType 方法返回正确的对象类型。
【解决方案2】:

还有一些其他技术可以帮助您解决测试问题:

使用您的真实数据库:

Spring Framework 对Testing 的支持允许您在设置期间启动事务,并在拆卸时回滚它们,因此数据库不会被测试数据弄得乱七八糟。对于复杂的设置DBUnit 可以提供帮助。正如您所指出的,这比单元测试需要更长的时间来运行。这就是为什么开发人员经常将集成测试分离到一个单独的套件中,该套件作为构建步骤而不是开发人员构建的一部分运行。

使用 MockRunner:

MockRunner 是一个用于创建假 JDBC 组件的库,您可以在其中填充结果集数据,而 JdbcTemplate 不知道其中的区别。我不确定您是否可以仅使用 Spring 创建一个 MockDataSource 而无需编写一些帮助类

在没有 Spring 接线的测试中使用 Mockito:

Mockito 最适合用于单元测试。因此,您的 DAO 测试不会使用 Spring 进行连接,您将创建一个单元测试,在其中创建您手动注入 DAO 的模拟 JdbcTemplate。

如果您尝试测试的不仅仅是单独的 DAO,并且想了解几个组件如何组合在一起进行真正的集成测试,那么模拟数据库将隐藏真实数据库中出现的实际问题。如果您只关心您的个人 DAO 在 JdbcTemplates 的模拟输出中正常运行,那么使用 Mockito 或 MockRunner 将允许您这样做。

【讨论】:

    猜你喜欢
    • 2019-01-05
    • 2016-02-23
    • 1970-01-01
    • 2013-02-09
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多