【问题标题】:How to unit test a DAO that is extending SqlMapClientDaoSupport如何对扩展 SqlMapClientDaoSupport 的 DAO 进行单元测试
【发布时间】:2008-09-21 09:06:52
【问题描述】:

Spring DA 有助于编写 DAO。当使用iBATIS作为持久化框架,扩展SqlMapClientDaoSupport时,应该为DAO设置一个SqlMapClient mock,但是我做不到。 SqlMapClientTemplate 不是接口,EasyMock 无法为其创建模拟。

【问题讨论】:

    标签: java spring ibatis easymock


    【解决方案1】:

    DAO 和单元测试不能很好相处! 在不包含任何业务逻辑且专注于数据库访问的组件中模拟任何内容是没有意义的。 您应该尝试编写集成测试。看看 spring 参考文档,第 8.3 章:http://static.springframework.org/spring/docs/2.5.x/reference/testing.html

    【讨论】:

    • 虽然我可以看到您的逻辑,但我可以设想可以从单元测试中受益的 DAO 功能。因此,我认为说 DAO 不应该进行单元测试是不公平的——这完全取决于所讨论的类。
    【解决方案2】:

    这正是我不从SqlMapClientDaoSupport 扩展的原因。相反,我向SqlMapClientTemplate(键入为接口SqlMapClientOperations)注入了一个依赖项。这是一个 Spring 2.5 示例:

    @Component
    public class MyDaoImpl implements MyDao {
    
        @Autowired
        public SqlMapClientOperations template;
    
        public void myDaoMethod(BigInteger id) {
            int rowcount = template.update("ibatisOperationName", id);
        }
    }
    

    【讨论】:

    • 组合比继承更好的另一个原因。
    【解决方案3】:

    正如@Banengusk 建议的那样——这可以通过Mockito 来实现。但是,重要的是要确定您的 DAO 将使用 Spring SqlMapClientTemplate 包装您的模拟 SqlMapClient。事实上,SqlMapClientTemplate 将调用委托给 IBatis 层中的SqlMapSession

    因此需要一些额外的模拟设置:

    mockSqlMapSession = mock(SqlMapSession.class);
    mockDataSource = mock(DataSource.class);
    
    mockSqlMapClient = mock(SqlMapClient.class);
    when(mockSqlMapClient.openSession()).thenReturn(mockSqlMapSession);
    when(mockSqlMapClient.getDataSource()).thenReturn(mockDataSource);
    
    dao = new MyDao();
    dao.setSqlMapClient(mockSqlMapClient);
    

    然后我们可以像这样验证行为:

    Entity entity = new EntityImpl(4, "someField");
    dao.save(entity);
    
    ArgumentCaptor<Map> params = ArgumentCaptor.forClass(Map.class);
    verify(mockSqlMapSession).insert(eq("insertEntity"), params.capture());
    assertEquals(3, params.getValue().size());
    assertEquals(Integer.valueOf(4), params.getValue().get("id"));
    assertEquals("someField", params.getValue().get("name"));
    assertNull(params.getValue().get("message"));
    

    【讨论】:

      【解决方案4】:

      试试Mockito。它允许模拟类,而不仅仅是接口。

      【讨论】:

        猜你喜欢
        • 2012-05-14
        • 2019-02-04
        • 2011-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-15
        • 2016-03-15
        相关资源
        最近更新 更多