如何覆盖gorm delete方法进行测试?

时间:2016-11-06 09:40:50

标签: grails integration-testing

我正在编写一个简单的集成测试,我打算模拟删除失败。

控制器只是从数据库中提取记录并删除它,如下所示。

def deleteItem(id){


    def item = Item.get(id)

    item.delete()

}

现在,我想使用以下代码模拟删除失败

void testDeleteItem_FailDeleteFlushSaveFail(){


    Item.metaClass.delete = { Map params ->

        throw new ValidationException("Failed!!")

    }



    def model = controller.deleteItem(mp.id)


    assertEquals controller.flash.message, "Sorry an error occured when deleting!!"



    GroovySystem.metaClassRegistry.removeMetaClass(Item.class)



}

但测试失败,因为该方法未被替换。即删除时不会抛出异常。我猜这个问题出在我的元类配方中。如何调用delete以便在调用delete时抛出异常?我感谢任何帮助!谢谢!

3 个答案:

答案 0 :(得分:0)

这是因为你应该使用

Item.metaClass.delete = {

        throw new ValidationException("Failed!!")

    }

而不是

Item.metaClass.delete = { Map params ->

        throw new ValidationException("Failed!!")

    }

答案 1 :(得分:0)

首先,我不认为这个问题应该被低估了。对于你想要测试你的程序如何对失败作出反应的场景,这是一个有效的问题。

这里有一些问题:

  • Domain.delete不会抛出validationExceptions。 ValidationExceptions也是用两个参数构造的(String msg,Errors error)。您需要向域类添加自定义错误并传入域类。再次,这对删除没有意义,因为谁需要在删除时验证对象? 不确定您正在运行的版本,但这里是2.5.1的文档(Grails 2.5.1 docs - 请参见7.3.2删除对象)

    def p = Person.get(1) 尝试{     p.delete(flush:true) } catch(org.springframework.dao.DataIntegrityViolationException e){     flash.message ="无法删除人$ {p.name}"     重定向(动作:"显示",id:p.id) }

  • 其次,删除(failOnError:true)。我不确定它会做什么。相反,你应该在try catch中包含你的delete方法,并使用flush:true选项。

    try{
        item.delete(flush:true)
    }catch(DataIntegrityViolationException e){
        flash.message = "Sorry an error occurred when deleting!!"
    }
    
  • 第三,mp.id来自哪里?我们是否遗漏了部分测试文件。如果没有,您的测试似乎依赖于已存在的数据。即使在集成测试中,最好以某种方式为每个测试单独创建数据,以防止测试污染和由于缺少数据而导致的测试失败。

  • 最后,我无法在集成测试中对Domain Class本身进行正确的metaClass ...所以我建议你在测试中使用metaClass域实例。这是一个例子:

MetaClass域实例方法:

//creating test data
def item = new Item(name: 'testName')

def model = controller.deleteItem(item.id)

item.metaClass.delete = {Map params ->
    throw new DataIntegrityViolationException('Some error message')
}

assertEquals controller.flash.message, "Sorry an error occurred when deleting!!"

编辑1注意 我忘了包括地图参数 - >'在metaClass闭包中。 (可能在所有版本的grails中都不需要,因为这些方法在不同版本中的编译方式不同)

答案 2 :(得分:-1)

尝试使用:

Item.metaClass.'static'.delete = { Map params ->
    throw new ValidationException("Failed!!")
}