Grails / GORM中集成测试“复合唯一约束”的问题?

时间:2013-11-23 01:12:17

标签: grails gorm

我正在尝试确保user只能vote给定project一次(不允许重复投票)。经过一些搜索,看起来有一个composite unique constraint来实现这一目标。但是,我在集成测试中遇到了一些问题。我的域类如下。

package grailstuts

class User {
    String name
    static hasMany = [ projects: Project, votes: Vote ]

    static constraints = { name(nullable: true) }

    static mapping = { projects cascade: "all-delete-orphan" }
}

package grailstuts

class Project {
    String title
    Set votes = []
    static belongsTo = [ user: User ]
    static hasMany = [ votes: Vote ]

    static constraints = { title(nullable: true) }
}

package grailstuts

class Vote {
    static belongsTo = [ user: User, project: Project ]

    static constraints = { user(unique: 'project') }
}

请注意unique课程中的Vote约束。然后我的集成测试看起来像这样:

package grailstuts

import spock.lang.*

class VoteIntegrationSpec extends Specification {

    void "Testing uniqueness"() {

        given: "A user and a project"
        def user = new User();
        def project = new Project();
        user.addToProjects(project)
        user.save(failOnError: true)

        when: "The user votes the project"
        def vote = new Vote()
        user.addToVotes(vote)
        project.addToVotes(vote)

        then: "The user should not be able to vote the same project again"
        def vote2 = new Vote()
        user.addToVotes(vote2)
        project.addToVotes(vote2)
    }
}

此集成测试没有任何错误。但是我认为这个测试应该失败,因为用户再次投票给同一个项目(在then:块中),这不应该基于static constraints = { user(unique: 'project') }中的Vote。类。似乎无法弄清楚这一点,任何人都可以指出我做错了什么吗?

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

此行为的原因是未验证测试。

由于投票是针对每个用户和每个项目(我的假设),因为您说您需要复合唯一性:

package grailstuts
class Vote {
    static belongsTo = [ user: User, project: Project ]
    static constraints = { 
           user unique: 'project'
    }
}

您的规范将是:

void "Testing uniqueness"() {

    given: "A user and a project"
        def user = new User()
        def project = new Project()
        user.addToProjects(project)
        user.save(failOnError: true)

    when: "The user votes the project"      
        def vote = new Vote(user:user,project:project).save()

    then: "The user should not be able to vote the same project again"      
       // def vote2 = new Vote(user:user,project:project).save(flush:true,failOnError:true)
       // or 
       new Vote(user:user,project:project).validate() == false
    }

答案 1 :(得分:1)

您没有测试投票是否已保存到数据库。你应该:

when: ...
vote.save()

then: ...
Vote.count() == 1

when: ...
vote1.save()

then:
Vote.count() == 1 // Constraint working

你需要用两个时间和两个来编写测试。当保存第一次投票然后Vote.count()== 1当保存第二次投票然后Vote.count()== 1

您可以使用单元测试代替集成测试。执行效率更高。