【问题标题】:How can I have a domain object's .save() method fail in an integration test?如何让域对象的 .save() 方法在集成测试中失败?
【发布时间】:2011-05-24 15:00:27
【问题描述】:

对于集成测试,我想有一个 .save() 故意以测试符合 else-condition。

我的测试班是这样做的:

来自 UserService.groovy:

User user = User.findByXyz(xyz) 
if (user) {
    // foo
    if (user.save()) {
        // bar
    } else {
        // I WANT TO GET HERE
    }
}

到目前为止我尝试过的方法都失败了:

我在 UserServiceTests.groovy 中尝试过的内容:

def uControl    = mockFor(User)
uControl.demand.save { flush -> null }  // in order to test a failing user.save()
def enabledUser = userService.enableUser(u.confirmationToken)
uControl.verify()

// or the following:
User.metaClass.'static'.save = { flush -> null }  // fails *all* other tests too

如何正确地从集成测试中进入 else 块?

【问题讨论】:

  • 更改用户的元类应该可以工作,您只需要先调用 registerMetaClass 以便在测试完成后恢复元类,如果您有,请不要忘记调用 super.tearDown()在你的课堂上实现它。

标签: testing grails groovy mocking integration-testing


【解决方案1】:

您几乎不需要在集成测试中模拟或更改元类 - 只有单元测试。

如果您想使save() 调用失败,只需传入未验证的数据即可。例如默认情况下所有字段都不为空,因此使用def user = new User() 应该会失败。

【讨论】:

  • 谢谢伯特。我已将User user = User.findByXyz(xyz) 添加为第一行,这反映了我目前的情况并解释了为什么我无法遵循您的建议。我该如何处理这种情况?
【解决方案2】:

也许您可以尝试将“验证”更改为其他内容 - 通过使用您展示的相同元类编程。 这样,如果验证失败,保存肯定会失败

【讨论】:

  • 不过我建议,您的集成测试应该只在其中一个字段未通过验证标准(即约束)时才期望保存方法失败。
  • 您能详细说明一下吗?我目前不知道尝试更改 validate() 和尝试更改 save() 之间的区别
【解决方案3】:

在这种情况下我会做什么: 我总是有至少一个不为空的字段。 我根本不设置它然后调用 .save() 如果您想在数据库中已经存在的对象上实现此目的,只需使用 find 或 get 加载它并将其中一个非 null 值设置为 null,然后尝试保存它。 如果您没有将 Config.groovy 配置为在保存时在失败时抛出异常,它不会抛出异常,它根本不会保存它[您可以预先调用 .validate() 来确定它是否会保存并检查object_instance.errors.allErrors 列表以查看错误]。

【讨论】:

    猜你喜欢
    • 2011-07-03
    • 2011-10-09
    • 1970-01-01
    • 2014-09-29
    • 2018-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多