gpt4 book ai didi

unit-testing - 在 Grails 单元测试中模拟静态 get gorm 方法

转载 作者:行者123 更新时间:2023-12-04 04:44:51 25 4
gpt4 key购买 nike

我正在使用 Grails 2.3.7。我有一个简单的 Person 域对象:

class Person {
String name
static constraints = {}
}

和 Controller :
@Transactional(readOnly = true)
class PersonController {
def index() {
render view:'index', model:[personList:Person.list()]
}

def show(Long id) {
def person = Person.get(id)
render view:'show', model:[person:person]
}
...
}

我正在尝试为 Controller 编写一个单元测试来练习 show方法,但我不确定我需要如何配置测试以确保静态调用 Person.get(id)返回一个值。

这是我的(失败)尝试:
import grails.test.mixin.*
import spock.lang.*

@TestFor(PersonController)
@Mock(Person)
class PersonControllerSpec extends Specification {

void "Test show action loads Person by id and includes that person in the model rendered"() {
setup:
def personMockControl = mockFor(Person)
personMockControl.demand.static.get() { int id -> new Person(name:"John") }

when:"A valid person id passed to the show action"
controller.show(123)

then:"A model is populated containing the person domain instance loaded by that unique id"
model.person != null
model.person.name == "John"
}
}

此测试失败,因为条件 model.person != null失败。我如何重写此测试以使其通过?

编辑

在这种情况下,我可以通过重新编写测试来回避静态方法调用:
void "Test show action loads Person by id and includes that person in the model rendered"() {
setup:
def p = new Person(name:"John").save()

when:"A valid person id passed to the show action"
controller.show(p.id)

then:"A model is populated containing the person domain instance loaded by that unique id"
model.person != null
model.person.id == p.id
model.person.name == "John"
}

但是,我真的很想了解如何正确模拟 Person的静态 get方法。

编辑 2

这是另一种情况来证明我认为需要模拟 get方法。鉴于此过滤器代码:
def fitlers = {
buyFilter(controller:"paypal", action:"buy") {
after = {
new VendorPayment(payment:request.payment, vendor: Vendor.get(params.buyerId)).save()
}
}
}

我正在尝试使用以下测试来测试此过滤器是否按预期工作:
void "test the buyFilter to ensure it creates a VendorPayment when the PayPal plugin controller is called" () {
setup:
// how do I mock the Vendor.get(params.buyerId)
// to return a vendor in order to save a new VendorPayment

when:
withFilters(action:"buy") {
controller.buy()
}

then:
VendorPayment.count() == 1
}

最佳答案

就像 dmahaptro 提到的,你不需要 mock 你的人。通过 .get() 在测试中抓取对象的首选/正确方式是您拥有它的方式——您创建域实例,并将其 id 传递给 Controller ​​操作以供使用。

但是,如果您需要模拟这样的静态方法,有两种方法:

1) 使用 mockFor方法由 GrailsUnitTestMixin 提供然后像这样指定静态方法:

GrailsMock mockPerson = mockFor(Person)
mockPerson.demand.static.get() { Long id -> new Person(name:"John") }

请注意,在您的情况下,模拟的静态 get方法未包含正确的参数类型(使用 int 而不是 Long),因此未调用此方法。

2) 修改类' metaClass .非常不鼓励更改元类(尤其是当 @Mock 注释已经为您设置了所有内容时),并且可能导致测试泄漏(即,更改元类后其他测试将无法正常工作,除非您恢复原始测试完成后的元类)。

也就是说,为了熟悉起见,您将模拟 .get() 的方式方法是通过:
Person.metaClass.static.get = { Long id -> return personWithId }
同样,这被认为是不好的做法,应该避免,但你已经做到了。

关于unit-testing - 在 Grails 单元测试中模拟静态 get gorm 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23352564/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com