unit-testinggroovyspock

Mocking ProductCategory findAll fails in Groovy Spock test


I have a class which associates Products with a ProductCategory. It uses a ProductCategoryRepository which is a MongoDB repository. The ProductCategoryRepository has a findAll methods which takes the productIds of the products and finds their corresponding ProductCategory. However when mock the findAll method in the spock test it fails;

Here is the code for the service


    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.mongodb.repository.Query;
    import org.springframework.stereotype.Repository;
    import org.springframework.stereotype.Service;
    import org.springframework.util.ObjectUtils;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    @Service
    @Slf4j
    public class ProductsLinkService {
    
        private final ProductCategoryRepository productCategoryRepository;
    
        @Autowired
        public ProductsLinkService(ProductCategoryRepository productCategoryRepository) {
            this.productCategoryRepository = productCategoryRepository;
        }
    
        public List<Product> process(List<Product> products) {
            if (ObjectUtils.isEmpty(products)) {
                return new ArrayList<>();
            }
            List<Long> productIds = MappingUtilityFunctions.retrieveIdsForDepartments(products);
            List<ProductCategory> productCategories = productCategoryRepository.findAll(productIds);
            return linkProductsWithCategory(products,productCategories);
        }
    
        private List<Product> linkProductsWithCategory(List<Product> products, List<ProductCategory> productCategories) {
            //...
        }
    }



The ProductCategoryRepository is a simple class with the findAll method


    import org.springframework.data.mongodb.repository.MongoRepository;
    import org.springframework.data.mongodb.repository.Query;
    import org.springframework.stereotype.Repository;
    import java.util.List;
    
    
    @Repository
    public inteface ProductCategoryRepository extends MongoRepository<ProductCategory, Long> {
    
        @Query(value = "{ '_id' : {'$in' : ?0 } }")
        List<ProductCategory> findAll(List<Long> productIds);
    }




Here is my Spock test for the ProductLinkService


     class ProductsLinkServiceSpec extends Specification {

        ProductCategoryRepository productCategoryRepository = Mock()
        List<Long> productIds =  [11L, 22L, 33L]
        ProductsLinkService productsLinkService

        def setup(){
            productsLinkService = new ProductsLinkService(productCategoryRepository)
        }

        def'Associating products with their product categories should be successful'(){
            given:
             List<Products> products = ....
             List<ProductCategory> productCategories = ...

             // Exception thrown here
             productCategoryRepository.findAll(productIds) >> productCategories
                     
            when:

              def productsWithCategories = productsLinkService.process(products)
              then:
                // assertions
           
        }
    }



I get the following error at the at the point where I do the findAll on the ProductCategoryRepository. Here is the exception:

groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.call() is applicable for argument types: () values: []
Possible solutions: tail(), tail(), wait(), any(), last(), tails()
at com.adx.batch.linking.ProductsLinkServiceSpec.Associating products with their product categories should be successful(ProductsLinkServiceSpec.groovy:25)



Solution

  • This fixed it

             productCategoryRepository.findAll(productIds) >> [productCategories[0], etc. ]