【问题标题】:How to write JUnit test of a class that uses anonymous inner class such as PreparedStatementSetter?如何编写使用匿名内部类(如 PreparedStatementSetter)的类的 JUnit 测试?
【发布时间】:2019-11-26 12:15:06
【问题描述】:

我有以下类,它使用匿名内部类 (new PreparedStatementSetter()) 在查询中使用 PreparedStatementSetter 设置值并返回对象的 List

问题是我不确定如何为这种方法编写单元测试。 一旦我的单元测试到达它调用getJdbcTemplate().query(......) 的行,它就会跳到行尾并且discAuditLogList 值返回null 并且单元测试完成而没有任何错误。 当我查看IntelliJ 中的代码覆盖率时,所有ps.setString 语句都没有被执行。

ProductLogDao.java

//bunch of setter getters here

public List<ProductLogDTO> getProductLogDetail(RequestDTO requestDTO) throws SQLException, DataAccessException {
    logger.info("Inside ProductLogDao.getProductLogDetail" + requestDTO);
    List<ProductLogDTO> productLogList = null;
    final Map<String, String> requestParamMap = requestDTO.getParameters();
    if ("custom".equalsIgnoreCase(requestParamMap.get("recordtype"))) {
        ProductLogList = getProductCustomDetail(senderFeeSql, requestParamMap);
        return ProductLogList;
    }
    return productLogList;
}


public List<ProductLogDTO> getProductCustomDetail(String senderFeeSql,
                                                          final Map<String, String> requestParamMap) throws SQLException {
    @SuppressWarnings("unchecked")
    List<ProductLogDTO> productLogList = getJdbcTemplate().query(senderFeeSql, new PreparedStatementSetter() {
        public void setValues(PreparedStatement ps) throws SQLException {
            /***************************************************************************************************************/
            //FOLLOWING STATMENTS NEVER GET EXECUTED BECAUSE THEY ARE WITHIN ANONYMOUS CLASS (new PreparedStatementSetter())
            /***************************************************************************************************************/
            ps.setString(1, requestParamMap.get("startDfId"));
            ps.setString(2, requestParamMap.get("startDfId"));
            ps.setString(3, requestParamMap.get("chanelId"));
            ps.setString(4, requestParamMap.get("chanelId"));
            ps.setString(5, requestParamMap.get("fromDateTime"));
            ps.setString(6, requestParamMap.get("toDateTime"));
            ps.setString(7, requestParamMap.get("fromDateTime"));
            ps.setString(8, requestParamMap.get("toDateTime"));
        }
    }, new ProductCustomRowMapper());

    if (null != productLogList && (productLogList.size() > 0)) {
        productLogList.get(0).setRecordtype("custom");
        productLogList.get(0).setRecordsFetched(productLogList.get(0).getRecordsFetched());
    }
    return productLogList;
}

ProductLogDaoTest.java

public class ProductLogDaoTest {

    ProductLogDao instance = new ProductLogDao();
    RequestDTO requestDTO = Mockito.mock(RequestDTO.class);
    JdbcTemplate jdbcTemplate = Mockito.mock(JdbcTemplate.class);
    Map<String, String> requestParamMap = new HashMap<>();

    @Before
    public void setUp() throws Exception {
        instance.setJdbcTemplate(jdbcTemplate);
    }

    @Test
    public void getProductLogDetail_W_Custom() throws SQLException, DataAccessException {
        when(requestDTO.getParameters()).thenReturn(requestParamMap);
        requestParamMap.put("recordtype", "custom");
        assertNotNull(instance.getProductLogDetail(requestDTO));
    }

}

【问题讨论】:

    标签: java spring junit spring-test spring-test-mvc


    【解决方案1】:

    你已经模拟了JdbcTemplate,但还没有模拟你的JdbcTemplate 方法。这就是它返回 null 的原因。

    您可以使用某种测试数据库。如果是 Spring,您可以使用嵌入式:https://docs.spring.io/spring/docs/3.0.0.M4/spring-framework-reference/html/ch12s08.html。有关在测试期间模拟数据库的更多信息,请参阅此问题:How to simulate a DB for testing (Java)?

    无论哪种方式,您都可以检查您的 query() 方法是否被 Mockito 的 verify() 方法调用。

    【讨论】:

      【解决方案2】:

      永远不要像这样在依赖对象中创建对象实例:new PreparedStatementSetter() 它几乎不连接此类实例,您无法将其更改为模拟。 始终执行以下操作之一:

      1. 通过工厂对象方法调用 (myBusinessFactoryInstance.createPreparedStatementSetter) 创建这些类实例。如果更改工厂,则可以创建模拟。

      2. 在 Spring 中,您可以通过构造函数或 setter 方法注入此依赖项。

      如果你这样做了,你的测试将会是一种魅力。

      【讨论】:

      • 感谢@The Bitman,有没有关于如何实施您的建议的指示?
      • 1.,研究Abstract FactoryFactory method 设计模式。 2.,阅读一些关于基础Spring机制的书籍。写详细的建议太长了。了解SOLID 建模原理、Clean Code 等。作为作者的 Rober Cecil Martin 是一个非常好的知识来源。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多