Unit testing 如何覆盖方法';在grails中使用mockDomain时的逻辑是什么?

Unit testing 如何覆盖方法';在grails中使用mockDomain时的逻辑是什么?,unit-testing,grails,mocking,dns,Unit Testing,Grails,Mocking,Dns,我想像往常一样用一切来模拟一个域(mockDomain(Class)),但我想用自定义逻辑覆盖该域的一个方法(beforeDelete,具体来说),只用于一个单元测试 这是如何实现的?像往常一样用mockDomain模拟域类,然后在一个特定的单元测试中用mockFor在删除之前模拟闭包。例如: void testDelete() { mockDomain(MyDomainClass) def myDomainClassControl = mockFor(MyDomainClass

我想像往常一样用一切来模拟一个域(
mockDomain(Class)
),但我想用自定义逻辑覆盖该域的一个方法(
beforeDelete
,具体来说),只用于一个单元测试


这是如何实现的?

像往常一样用
mockDomain
模拟域类,然后在一个特定的单元测试中用
mockFor
在删除之前模拟
闭包。例如:

void testDelete() {
    mockDomain(MyDomainClass)
    def myDomainClassControl = mockFor(MyDomainClass)
    myDomainClassControl.demand.beforeDelete(1..1) { -> println "hello world" }

    ... // test delete

    myDomainClassControl.verify()
}

您可以使用Groovy元类覆盖域类上的beforeDelete方法

域类:

class Person {
  String name
  boolean deleted

  def beforeDelete() {
    println "Deleting Person ${id}"
    deleted = true
    return false
  }
}
单元测试:

void testBeforeDelete() {
    mockDomain(Person)
    def p = new Person(name:"test")
    p.save()
    assertEquals false, p.deleted
    p.delete()
    assertEquals true, p.deleted
}
--testBeforeDelete的输出--

删除第1人

void testBeforeDeleteOverrideBeforeDelete() {
    mockDomain(Person)
    Person.metaClass.'static'.beforeDelete = {println 'Do not touch me'}
    def p = new Person(name:"test")
    p.save()
    assertEquals false, p.deleted
    p.delete()
    assertEquals true, p.deleted
}
--testBeforeDeleteOverrideBeforeDelete的输出--


请勿触碰我

如何获取域类的实例?当我执行def md=new MyDomainClass()和更高版本的md.save()时,测试仍然运行原始的beforeDelete()。另一方面,如果我确实执行了def md=myDomainClassControll.createMock(),则md.save()会导致java.lang.IllegalArgumentException:参数类型不匹配参数类型不匹配似乎只有在删除mockDomain(MyDomainClass)时才会消失,但随后我会收到junit.framework.AssertionFailedError:verify[2]:预期的1..调用在grails 1.3.7的单元测试中,
beforeDelete
事件似乎不会被触发。作为替代方案,我建议将测试转换为集成测试。我从集成转换是为了减少那里的测试量:)太好了!谢谢,大卫。你能告诉我在这种情况下“静态”是什么意思吗?在上面的示例中,我们使用ExpandoMetaClass在Person类上添加/重写静态方法。