Home > other >  Spock returns empty list when mocking JdbcTemplate
Spock returns empty list when mocking JdbcTemplate

Time:04-21

I have a service class that uses a JdbcTemplate to perform a search using product ids and returns the matched products.

Here is the class

@RequiredArgsConstructor

@Service public class ProductService {

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;
}

Here is the test 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
}

}

I tried using a stub for the jdbcTemplate to return a list of Products like so, but the list is empty

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

However, when I debug, it returns a product list with size 0, even though there are 3 elements in the product list. Is this expected? If so does that mean it is not possible to mock or stub the JdbcTemplate in Spock? I would really appreciate if someone could help me with this issue.

I tried this as well and it did not work;

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

and

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

CodePudding user response:

You defined the QueryBuilderUtility as a mock:

QueryBuilderUtility queryBuilderUtility = Mock()

I.e., every method call returns null. So you either need to use a real query builder utility instead of a mock or make sure to stub the method result, e.g.

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
}

Now the test should pass.

By the way: In this simple case where you do not seem need any value constraints for the method parameters of jdbcTemplate.query but _ for each, you could also simply write:

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

Update: See my full example project with several dummy classes I created in order to make your example code work:

Try it in the Groovy Web Console.

  • Related