【问题标题】:Grails testing a failing domain save in serviceGrails 测试失败的域保存在服务中
【发布时间】:2016-02-01 20:09:28
【问题描述】:

我有一个 Grails (3+) 服务,从数据库中检索域对象,修改,然后在数据库中更新。

class MyService {
    def modifyObject(String uuid) {
        def md = MyDomain.findByUuid(uuid)
        md.someField = true
        if (!md.save()){ 
            throw new MyException()
        }
    }
}

现在我需要用否定测试来测试这个服务方法,以确保抛出异常。但我不知道如何在服务方法中强制失败的save。

@TestFor(MyService)
@Mock(MyDomain)
class MyServiceSpec extends Specification {

    void "test An exceptionl situation was found"() {
        given: "An uuid"
            def md = new MyDomain(uuid: "123")
            md.save(failOnError: true)

        when: "service is called"
            service.modifyObject("123")

        then: "An exception is thrown"
            thrown MyException
    }
}

显然,以更实用的方式重新定义服务方法(对象直接传递给方法,修改并返回不保存.例如MyDomain modifyObject(MyDomain md))将是一个很好的解决方案,因为我可以在外部创建一个无效的 ad hoc 对象,甚至在方法执行后使其无效。

但问题是:“有没有办法按原样测试服务代码?”

【问题讨论】:

  • 违反对 MyDomain 的约束并且保存应该失败,不是吗?如果 modifyObject 真的那么简单(你不能传入一个虚假的值来强制违反约束),也许你需要对 MyDomain.save 进行 metaClass 并在那里强制失败。
  • @railsdog 如果您提供完整的工作答案,我可以接受

标签: unit-testing grails spock


【解决方案1】:

假设您确实想抛出异常而不仅仅是处理验证错误,那么可以确定。您将希望利用 Spock 对基于交互的测试的支持并利用静态方法存根。查看类似问题,Unit test grails with domain objects using GORM functions。

您需要一些方法来隔离服务方法并存根 GORM 功能。这对于静态方法可能很棘手,但可以使用全局 GroovyMock 或GroovySpy 来完成。本质上,您将在方法执行期间替换所有对 MyDomain 的实例/引用(尽管除非交互匹配,否则 GroovySpy 将依赖于实际的域类)。

使用 Mock/Spy 后,您可以指定预期发生的交互并指定这些交互应返回的内容。在这种情况下,我们希望 findByUuid 被调用一次,参数为 "123",并且我们返回一个模拟的 MyDomain 对象。然后,该模拟对象在我们返回 null 时调用它的 save() 方法,即保存失败。

void "test An exceptional situation was found"() {
    setup:
        GroovySpy(MyDomain, global: true)
        def mockDomain = Mock(MyDomain)

    when: "service is called"
        service.modifyObject("123")

    then: "An exception is thrown"
        1 * MyDomain.findByUuid("123") >> mockDomain
        1 * mockDomain.save() >> null
        thrown Exception
}

【讨论】:

    【解决方案2】:

    如果您违反了对 MyDomain 的约束并且保存应该失败,不是吗?

    如果 modifyObject 真的那么简单,并且您不能传入虚假值来强制违反约束,那么您可能需要对 MyDomain.save 进行元分类并在此处强制失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      • 1970-01-01
      • 2014-02-14
      相关资源
      最近更新 更多