grails - 在Spock Framework中继承。我想在多个规范中重用测试用例

标签 grails spock

在我的项目中,我有很多彼此非常相似的 Realm 对象。在设计测试时,我意识到很多测试用例是相同的。因此,我开始创建一个BaseSpec,使我能够重用逻辑和代码。

  • 我下面描述的方法正确吗?
  • 我如何执行除BaseSpec之外的所有单元测试?

  • 假设我有以下两个grails域类:
    class Product{
        String productName
        static constraints = {
            name nullable: false, blank: false, unique: true
        }
    
    }
    
    class Category{
        String categoryName
        static constraints = {
            name nullable: false, blank: false, unique: true
        }
    }
    

    首先,我需要一个Spec作为基础。该库将对ProductSpec和Category Spec进行通用测试。
    @Mock([Product, Category])  //? is this needed
    class BaseSpec extends Specification {
        @Shared classForTest
        @Shared constructor
        @Shared nameParam
    
        def setup(){
            //This is what I would override in my child Tests
            //classForTest =  new Category().getClass()
            //constructor = classForTest.getConstructor()
            //nameParam = "categoryName"
    
        }
    
    
        def "Testing that the name field is unique"(){
            given: "A class instance"
                String testValue = "ABSCSD SDS SDS"
                def instance1 = constructor.newInstance()  //using the constructor to get an instance
                instance1."${nameParam}" = testValue
                instance1.save(flush: true, failOnError: true)
            and: "A duplicated Instance"
                def instance2 = constructor.newInstance()
                instance2."${nameParam}" = testValue
            expect: "The second instance should not save"
                shouldFail {instance2.save(flush: true, failOnError: true)}
        }
    
        //...Other common test cases
    
    
    }
    

    然后,我将拥有一个ProductSpec和CategorySpec,并且每个都应该仅覆盖BaseSpec的设置。
    @TestFor(Product)
    class ProductSpec extends BaseSpec{
        @Override
        def setup(){
            classForTest =  new Product().getClass()  //Get the class that is testec
            constructor = classForTest.getConstructor() //Get the constructor of the tested class
            nameParam = "productName" //Establish the name of the parameter
        }
    
        //... Other Product Tests
    }
    
    @TestFor(Category)
    class CategorySpec extends BaseSpec {
        @Override
        def setup(){
            classForTest =  new Category().getClass()
            constructor = classForTest.getConstructor()
            nameParam = "categoryName"
        }
        //... Other Category Tests
    }
    

    最佳答案

    这是我最初发布的替代方法。 它不使用继承,但是将允许测试用例非常相似的测试用例。

    Consider the domain classes
    class Product{
        String productName
        static constraints = {
            name nullable: false, blank: false, unique: true
        }
    
    }
    
    class Category{
        String categoryName
        static constraints = {
            name nullable: false, blank: false, unique: true
        }
    }
    

    作为一个非常简单的示例,我们要测试productName和categoryName的验证。因此我们可以进行如下测试:
    @Mock([Product, Category])
    class CatalogSimpleGenericSpec extends Specification {
    
        def "Validation of test field in a given domain"(){
            given: "A new instance of the domain"
                def testInstance = constructorOfInstance.newInstance()  //Creating the instance using the constructor
                testInstance."${fieldName}" = fieldValue 
                testInstance.validate()
    
            expect: "Testing if the instance should save depending on the value of shouldHaveErrors"
                assert testInstance.hasErrors() == shouldHaveErrors //Verifying if it should have errors
    
                //If there are errors the instance should fail to save, otherwise it will save perfectly
                shouldHaveErrors ?
                    shouldFail {testInstance.save(flush: true, failOnError: true)}
                    : testInstance.save(flush: true, failOnError: true)
    
            where:
                constructorOfInstance                               | shouldHaveErrors  | fieldName | fieldValue                | reasoning
                //-----------------  PRODUCT ----------------------
                new Product().getClass().getConstructor()           | false             | "productName" | "Folders"             | "Should pass since a product name is supplied"
                new Product().getClass().getConstructor()           | true              | "productName" | ""                    | "Should fail empty strings should not be accepted"
                new Product().getClass().getConstructor()           | true              | "productName" | null                  | "Should fail null values shoult not be accepted"
    
                //----------------- CATEGORY --------------------
                new Category().getClass().getConstructor()          | false             | "categoryName" | "Office Supplies"    | "Should pass since a category name is supplied"
                new Category().getClass().getConstructor()          | true              | "categoryName" | ""                   | "Should fail empty strings should not be accepted"
                new Category().getClass().getConstructor()          | true              | "categoryName" | null                 | "Should fail null values shoult not be accepted"
        }
    
    
    } 
    

    我没有使用继承,而是获取域实例的构造函数,然后使用该构造函数(constructorOfInstance)构建我的实例(testInstance)。字段值是使用testInstance."${fieldName}" = fieldValue分配的。然后,我们使用 shouldHaveErrors 的值来测试保存是否失败。

    关于grails - 在Spock Framework中继承。我想在多个规范中重用测试用例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35782540/

    相关文章:

    gradle - 与Grab一起使用gradle时,如何确定我的规范的执行顺序?

    javascript - 带有 Grails <content> 标签的 Angularjs

    grails - 如何在application.js中引用grails.app.context?

    grails - Grails字段插件-自定义集合显示成员作为链接

    grails - Grails geb从命令行获取参数

    grails - java.lang.IllegalStateException : Could not find ApplicationContext, 首先正确配置 Grails

    grails - 如何在 grails 3.3.11 中深度克隆域对象?

    hibernate - Grails 2.4.3集成测试错误java.lang.NoClassDefFoundError:org/springframework/mock/web/MockAsyncContext

    grails - grails “test-app”无法通过功能性geb + spock测试,但是 “test-app -functional”成功

    where-clause - 如何在 spock 测试的 where 子句中调用方法或闭包