Grails:如何测试联想?

时间:2019-07-14 12:01:50

标签: grails gorm

我确定这个问题已经被回答过了,但是在文档或其他地方找不到。 我如何(单元?)在grails域模型类中测试关联?

例如,如果我有以下课程:

class StudentClass {

    static hasMany = [students: Student]

    static mapping = {
        students cascade: "none"
    }
}

class Student {
    String name

    static belongsTo = [studentClass: StudentClass]

}

如何测试“ hasMany”及其层叠?

编辑:

换句话说,我想测试将此配置添加到模型中的效果,以确保它满足我的需求。

例如,我希望能够做类似的事情(假设我了解关联文档;可以将其更改为更好的测试或在出错时进行修复)

def sc = new StudentClass().save()

new Student(studentClass: sc, name: 'name1').save()
assert StudentClass.count() == 1
assert StudentClass.get(1).students.size() == 1
assert StudentClass.get(1).get(0).name == 'name'

StudentClass.delete(1)
assert Student.count() == 1

谢谢

1 个答案:

答案 0 :(得分:0)

最近,我试图了解级联更新和删除在GORM中是如何工作的,并遇到了您的问题。在遇到用于测试一对多关系的单元测试问题之后,我对Grails的闲置通道提出了一个问题,有人建议我们可以创建一个集成测试,因为级联可能不适合与单元测试一起运行。

让我们如下创建域类。

SchoolClass.groovy

package com.itersdesktop.javatechs.grails.gorm

class SchoolClass implements Serializable{
    // for example: Class 1 or Owl class
    String name
    // year 1, year 2, etc.
    Integer year
    // for example: 2018-2019
    String schoolYear
    // there are at least two teachers: main and assistant
    static hasMany = [teachers: SchoolTeacher, pupils: Pupil]

    static mapping = {
        teachers cascade: 'all-delete-orphan'
        pupils cascade: 'all-delete-orphan'
    }

    static constraints = {
    }
}

SchoolTeacher.groovy

package com.itersdesktop.javatechs.grails.gorm

class SchoolTeacher implements Serializable {
    String name

    static belongsTo = [schoolClass: SchoolClass]

    static constraints = {
    }
}

学生班

package com.itersdesktop.javatechs.grails.gorm

class Pupil implements Serializable {
    String name
    static belongsTo = [schoolClass: SchoolClass]

    static constraints = {
    }
}

如您所见,SchoolClass具有teacherspupils属性,可以在其上设置更新和删除级联。我们要验证的是,只要销毁了学校课程实例,学生就会自动被移除。为此,我分别进行了名为SchoolClassSpec.groovySchoolClassItSpec的单元测试和集成测试。 enter image description here

SchoolClassSpec.groovy

package com.itersdesktop.javatechs.grails.gorm

import grails.testing.gorm.DomainUnitTest
import spock.lang.Specification

class SchoolClassSpec extends Specification implements DomainUnitTest<SchoolClass> {
    SchoolClass schoolClass
    Pupil p

    void setupData() {
        schoolClass = new SchoolClass(name: "Owl class", year: 2, schoolYear: "2017-2018")
        p = new Pupil(name: "Tony Nguyen")
        schoolClass.addToPupils(p)
    }

    void "test SchoolClass domain"() {
        given: "let's create a school class and a pupil"
        setupData()
        when: "save the school class"
        schoolClass.save()
        then: "we also save the pupil because we set cascade on SchoolClass"
        1 == SchoolClass.count
        1 == Pupil.count
        when: "get the school class and the pupil back"
        p = Pupil.get(1)
        schoolClass = SchoolClass.get(1)
        then: "we hope the returned values match with the inputs"
        p.name == "Tony Nguyen"
        schoolClass.name == "Owl class"
        schoolClass.schoolYear == "2017-2018"
        when: "let's delete the school class"
        schoolClass.delete(flush: true)
        then: "we hope the pupil will be deleted as well"
        0 == SchoolClass.count
        1 == Pupil.count
    }
}

注意:最后一行1 == Pupil.count是因为如果我们测试0 == Pupil.count,则测试将失败。 Spock-Reports插件生成的测试报告类似于以下屏幕截图。 enter image description here

让我们使用上面相同的代码,但是要进行如下所述的集成测试。

SchoolClassItSpec.groovy

package com.itersdesktop.javatechs.grails.gorm

import grails.testing.mixin.integration.Integration
import grails.transaction.Rollback
import spock.lang.Specification

@Integration
@Rollback
class SchoolClassItSpec extends Specification {
    SchoolClass schoolClass
    Pupil p

    void setupData() {
        schoolClass = new SchoolClass(name: "Owl class", year: 2, schoolYear: "2017-2018")
        p = new Pupil(name: "Tony Nguyen")
        schoolClass.addToPupils(p)
    }

    void "test SchoolClass domain"() {
        given: "let's create a school class and a pupil"
        /*SchoolClass schoolClass = new SchoolClass(name: "Owl class", year: 2, schoolYear: "2017-2018")
        Pupil p = new Pupil(name: "Tony Nguyen")
        schoolClass.addToPupils(p)*/
        setupData()
        when: "save the school class"
        schoolClass.save()
        then: "we also save the pupil because we set cascade on SchoolClass"
        1 == SchoolClass.count
        1 == Pupil.count
        when: "get the school class and the pupil back"
        p = Pupil.get(1)
        schoolClass = SchoolClass.get(1)
        then: "we hope the returned values match with the inputs"
        p.name == "Tony Nguyen"
        schoolClass.name == "Owl class"
        schoolClass.schoolYear == "2017-2018"
        when: "let's delete the school class"
        schoolClass.delete(flush: true)
        then: "we hope the pupil will be deleted as well"
        0 == SchoolClass.count
        0 == Pupil.count
    }
}

运行此集成测试,我得到了报告捕获的截图,如下所示。 enter image description here

讨论 我们可以从测试中得出的结论是:

  • 集成测试适用于级联删除操作。
  • 当我们删除包含学生列表或负责老师列表的学校班级实例时,尽管我们没有在的每个元素上明确调用删除操作,但将删除学校班级的学生和老师这些清单。我认为该测试说明了级联在关系数据库中的工作方式。