Spock returns 模拟 JdbcTemplate 时为空列表

Spock returns empty list when mocking JdbcTemplate

我有一项服务 class,它使用 JdbcTemplate 执行使用产品 ID 和 return 匹配产品的搜索。

这是class

@RequiredArgsConstructor

@服务 public class 产品服务 {

private final QueryBuilderUtility queryBuilderUtility;

private final JdbcTemplate productJdbcTemplate;

public ProductService(@Qualifier("productJdbcTemplate") JdbcTemplate productJdbcTemplate, QueryBuilderUtility queryBuilderUtility) {
    this.productJdbcTemplate = productJdbcTemplate;
    this.queryBuilderUtility = queryBuilderUtility;
}


public List<Product> findProducts(List<Long> productCodes) {
    String productQuery = queryBuilderUtility.buildSelectQuery(productCodes);
    List<Product> products = productJdbcTemplate.query( productQuery, new ProductRowMapper(), productCodes.toArray());
    return products;
}

这里是测试class:

 class ProductServiceSpec extends Specification { 
 
JdbcTemplate jdbcTemplate = Mock()
QueryBuilderUtility queryBuilderUtility = Mock()
ProductService productService
List<Long> productCodes =  [33334L, 66754L, 56772L]
TestUtil testUtil = new TestUtil();
List<Product> products = testUtil.createProducts()

def setup(){
    productService = new ProductService( jdbcTemplate, queryBuilderUtility)
}

def 'Find Products for product codes'(){

    given:

    1 *  jdbcTemplate.query(_ as String, _ as ProductRowMapper, _ as Object []) >> products

    when:
    //1 *  jdbcTemplate.query(_ as String, _ as ProductRowMapper, _ as Long []) >> products
    assert products.size() == 3



    List<Product> result = productService.findProducts(productCodes)
    println "Result is ${result}" // empty list
    then:
    1 == 1
}

}

我尝试使用 jdbcTemplate 的存根来 return 类似这样的产品列表,但该列表是空的

  List<Product> products = ...   
  JdbcTemplate jdbcTemplate = Stub()
  jdbcTemplate.query(_ as String, _ as ProductRowMapper, _ as Long []) >> products

但是,当我调试时,它 return 是一个大小为 0 的产品列表,即使产品列表中有 3 个元素。这是预期的吗?如果是这样,是否意味着不可能在 Spock 中模拟或存根 JdbcTemplate?如果有人能帮助我解决这个问题,我将不胜感激。

我也试过了,还是不行;

JdbcTemplate template = Mock()
1 * template.query(_ as String, _ as ProductRowMapper, _ as Object[]) >> products

1 * template.query(_ as String, _ as ProductRowMapper, _ as Long[]) >> products
    

您将 QueryBuilderUtility 定义为模拟:

QueryBuilderUtility queryBuilderUtility = Mock()

即每个方法调用 returns null。因此,您要么需要使用真正的查询构建器实用程序而不是模拟,要么确保对方法结果进行存根,例如

def 'Find Products for product codes'() {
  given:
  1 * jdbcTemplate.query(_ as String, _ as ProductRowMapper, _ as Object[]) >> products
  queryBuilderUtility.buildSelectQuery(_) >> "my query"

  expect:
  productService.findProducts(productCodes).size() == 3
}

现在测试应该通过了。

顺便说一下:在这种简单的情况下,您似乎不需要 jdbcTemplate.query 的方法参数的任何值约束,但每个 _ ,您也可以简单地写:

  1 * jdbcTemplate.query(*_) >> products

更新:查看我的完整示例项目,其中包含我创建的几个虚拟 类 以使您的示例代码工作:

Groovy Web Console 中尝试。