【问题标题】:Validate() returns false but it has been saved in the databaseValidate() 返回 false 但已保存在数据库中
【发布时间】:2015-03-09 15:54:58
【问题描述】:

我开始使用 grails,但我偶然发现了一种我不理解的行为。

给定这个域类

class Team {

    String name
    Date since
    Date until

    static hasMany = [teamMembers:Player]

    static constraints = {
        name nullable: false, blank: false, unique: true
        until nullable: true
        until(validator: { val, obj ->
            val?.after(obj.since)
        })

        teamMembers maxSize: 8
        //teamMembers size: 0..8
    }
}

我想要一个集成测试来检查一个团队中实际上不能有超过 8 名球员,所以我写了一个简化版本:

void "The team can only have up to 8 players"(){

    given:
    Player[] players = (1..9).collect {new Player(name: "Foo")}

    Team t = new Team(name:"Bar", since: new Date())

    expect:
    players.each {it.validate()}
    t.validate()

    when:

    players.each {it.save()}
    t.save()

    players.each {t.addToTeamMembers(it)}

    then:
    t.validate() == false
    t.getTeamMembers().size() == 9
    Team.get(t.id).teamMembers.size == 9
    Team.first().teamMembers.size == 9
    Team.findAll()[0].teamMembers.size == 9
    Team.findByName("Bar").teamMembers.size == 9
}

据我所知,getfind * 等会访问数据库。那么为什么我的团队无法验证(预期行为)但数据库中有 9 名玩家? 我错过了什么?

注意:名称不是玩家的 PK,我已经测试了约束、大小和 maxSize。

【问题讨论】:

  • employees.each ?你是说players.each吗?
  • 这是单元测试还是集成测试?
  • @codehx 是的,players.each
  • 所以我的回答对你没有帮助?
  • @BurtBeckwith 集成测试

标签: grails grails-orm spock


【解决方案1】:

与这个问题有关,I have found this answer from Peter Ledbrook

作为此链接的摘要:

...只要您在 Team 对象上调用“save()”,它 附加到会话。对该对象的任何后续更改都将 然后被持久化到数据库包括你添加的任何玩家

如果这是正确的(我还没有真正尝试过),那应该可以解决它:

void "The team can only have up to 8 players"(){

given:
   Player[] players = (1..9).collect {new Player(name: "Foo")}

   Team t = new Team(name:"Bar", since: new Date())

expect:
   players.each {it.validate()}
   t.validate()

when:
   players.each {t.addToTeamMembers(it)}
   t.save()      

then:
   !t.validate()
}

这意味着应该只保存一次团队对象(假设 Player 有一个属于 Team 域类)。让我知道这是否有效。

【讨论】:

  • 就是这样,虽然它对我有帮助,您能否编辑您的答案,使其至少包含链接中答案的简短摘要?
【解决方案2】:

这是一个错误吗? employees.each {t.addToTeamMembers(it)}?
因为你没有employees 变量。

假设你想说players.each {t.addToTeamMembers(it)}

如果你想测试坚持,我认为你需要在players.each {t.addToTeamMembers(it)} 之后说 t.save() 。

您的测试没有失败,因为您的团队人数为 9,但您实际上并没有拯救团队。

所以在when之前尝试保存

【讨论】:

  • 在 t.addToTeamMembers() 之后添加 t.save() 会呈现相同的结果。
  • t.save(flush:true, failOnError:true) 怎么样?
  • flush: true 不会改变结果,failOnError 显然会使测试失败。我的问题更多的是,如果 get、find 以及所有这些方法是否命中数据库,如果没有,为什么?
猜你喜欢
  • 2018-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-05
相关资源
最近更新 更多