我正在尝试为grails控制器编写单元测试用例,该控制器具有以下结构:
class MyController{
def save(){
def myDomain = new MyDomain(params)
business validation 1
business validation 2
myDomain.writedatasource.save()
business validation 3
business validation 4
}
}
由于单元测试未加载Datasource.groovy,因此 writedatasource 在单元测试期间不可用,因此“业务验证3”和“业务验证4”的测试用例失败,因为我< / p>
groovy.lang.MissingPropertyException:没有这样的属性:类的writedatasource:MyDomain
如何修改测试用例以测试验证方案3和4?
测试用例很简单,如下所示:
void testSave(){
...setup...
controller.save()
assert conditions
....
}
答案 0 :(得分:1)
不确定这是否可以解决问题,但您可以尝试:
def 'the controller call the save method in writedatasource'() {
given:
def calls = 0
and:
def myDomainInstance = new MyDomain()
and:
MyDomain.metaClass.getWritedatasource = { new Object() }
and:
Object.metaClass.save = { Map attrs ->
calls++
}
when:
controller.save()
then:
calls == 1
}
但你唯一要做的就是测试在writedatasource下调用save,所以最好也进行集成测试。如果这样做,请在http://grails.1312388.n4.nabble.com/Mocking-in-a-unit-test-a-domain-object-multiple-datasources-td4646054.html回答,因为他们似乎有同样的问题。
答案 1 :(得分:1)
解决原始问题:
我遇到了这个问题,不得不嘲笑许多方法,而不仅仅是拯救&#39;在多个域上。所以相反,我覆盖了我的域的getter,只是简单地返回调用域实例:
def setup() {
[MyDomain1, MyDomain2].each { Class clazz ->
mockDomain(clazz)
clazz.metaClass.getWritedatasource = {
return delegate
}
clazz.metaClass.'static'.getWritedatasource = {
return delegate
}
}
}
这也使我免于包含@DirtiesRuntime,因为我没有更新任何我想要清理的metaClass。
最重要的是,无论是调用数据源,无论是域类还是实例,它都应该使用mockDomain的GORM功能进行修饰,这意味着我不必模拟任何GORM方法。
如果您需要动态数据源,该怎么办?
在我的特定情况下,数据源是可配置的,可能会根据环境而改变。如果您处于类似情况,可以在域映射中进行配置:
static mapping = {
datasources Holders.grailsApplication?.config.dynamic?.datasources
...
}
其中dynamic.datasources是数据源名称的数组。然后,在测试设置中:
def setup() {
grailsApplication.config.dynamic.datasources = ['foo', 'bar']
[MyDomain1, MyDomain2].each { Class clazz ->
mockDomain(clazz)
grailsApplication.config.dynamic.datasources.each{
clazz.metaClass."get${it.capitalize()}" = {
return delegate
}
clazz.metaClass.'static'."get${it.capitalize()}" = {
return delegate
}
}
}
}