gpt4 book ai didi

unit-testing - chalice 2.4.4 : How do mock a transient service inside a domain?

转载 作者:行者123 更新时间:2023-11-28 20:54:47 24 4
gpt4 key购买 nike

我已经尝试解决这个问题 2 天了,我真的很困惑和沮丧。我有一个域对象,其中包含用于自定义验证的服务。域如下所示:

class Llama { 
String name
transient myFetcherService

static transients = [
'myFetcherService'
]

static constraints = {
name validator: { val, obj ->
if (obj.nameExists(val) == true) {
//return some error here.
}
}
}

protected boolean nameExists(String name) {
List<Llama> llamasList = myFetcherService.fetchExistingLlamasByName(name)

if (llamasList.isEmpty()) {
return false
}

return true
}
}

现在,我有另一个服务,它只保存一个 Llama 对象列表。它看起来像这样:

class LlamaFactoryService {

public void createLlamas(List<String> llamaNames) {
llamaNames.each { name ->
new Llama(name: name).save()
}
}

}

在我的测试中。我不断收到此错误:

Failure:  createLlamas should create Llammas (com.myLlamaProject.LlamaFactoryServiceSpec)
| java.lang.NullPointerException: Cannot invoke method myFetcherService on null object

我不明白。在我的测试中,在“给定”部分为服务添加了一个元类。当它尝试保存时,它告诉我们该服务为空。这是我的测试的样子:

given:
def myFetcherService = mockFor(MyFetcherService)
myFetcherService.demand.fetchExistingLlamasByName {def name -> return []}
Llama.metaClass.myFetcherService = myFetcherService.createMock()

when:
service.createLlamas(['Pablo','Juan','Carlos'])

then:
//some validations here....

我还尝试在方法 nameExists() 上使用元类,例如:

Llama.metaClass.myFetcherService = { def name -> false }

,但它给了我与上面相同的 nullPointerException。有人能指出我正确的方向吗?我有点卡住了。 :(

在此先感谢您的阅读和帮助。

最佳答案

您正在使用单元测试,单元测试的一般规则是通常不会为您创建 bean,因此您需要自己注入(inject)它们。

(编辑代码以反射(reflect)我误读了问题的事实)我想你想要一个像这样的测试模式:

given:
def mockMyFetcherService = Mock(MyFetcherService) // create the mock
Llama.metaClass.getMyFetcherService = { mockMyFetcherService } // inject the dependency
def returnList = [] // let's just define this here and you can re-use this pattern in other tests more easily

when:
service.createLlamas(['Pablo','Juan','Carlos'])

then:
// tell Spock what you expect to have happen with your Mock - return the List you defined above
3 * mockFetcherService.fetchExistingLlamasByName(_) >> returnList

如果将服务注入(inject)到元类中不起作用(suggested here),您始终可以尝试在单元测试本身(http://www.block-consult.com/blog/2011/08/17/inject-spring-security-service-into-domain-class-for-controller-unit-testing/)中使用 defineBeans{} 闭包。

因此你可以尝试:

defineBeans {
myFetcherService(MockMyFetcherService)
}

其中 MockMyFetcherService 在定义测试的同一个文件中定义。这是方法followed here :

参见 here有关更多 Spock 交互的示例。

如果您使用的是 Grails 2.4.3 或更低版本,则需要将 CGLIB 放入 BuildConfig.groovy 中,但我看到了 here它已经在 2.4.4 中为您完成,所以您应该可以使用 Mock(classname)

关于unit-testing - chalice 2.4.4 : How do mock a transient service inside a domain?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28816354/

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