我有一个 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)
)将是一个很好的解决方案,因为我可以在外部创建无效的临时对象或甚至在方法执行后使其无效。但问题是:“ 有没有办法按原样测试服务代码?”
最佳答案
假设您确实想抛出异常而不仅仅是处理验证错误,那么可以确定。您将希望利用 Spock 对基于交互的测试的支持并利用静态方法 stub 。见类似问题,Unit test grails with domain objects using GORM functions .
您需要一些方法来隔离服务方法并 stub GORM 功能。这对于静态方法可能很棘手,但可以使用全局 GroovyMock 或 GroovySpy 来完成。 .本质上,您正在替换所有实例/对 MyDomain
的引用。在方法的持续时间内(尽管 GroovySpy 将依赖于实际的域类,除非交互匹配)。
有了 Mock/Spy,您可以指定您期望发生的交互,并指定这些交互应该返回什么。在这种情况下,我们期望 findByUuid
使用参数 "123"
调用一次,我们返回一个模拟 MyDomain
目的。然后那个模拟对象有它 save()
方法在我们返回 null 的地方调用一次,即保存失败。
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
}
关于unit-testing - Grails 测试失败的域保存在服务中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35085787/