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.