What are the restrictions of Grails' mockDomain() method?
I'm writing a Spock Spec (unit test) for a Service in Grails 1.3.5, and I've run across the following error:
No signature of method: myapp.Thing.findAll() is applicable for argument types: (java.util.LinkedHashMap) values: [[sort:index, order:asc]] Possible solutions: findAll(), findAll(groovy.lang.Closure), find(groovy.lang.Closure), getAll(java.util.List), getAll([Ljava.lang.Object;)
groovy.lang.MissingMethodException: No signature of method: myapp.Thing.findAll() is applicable for argument types: (java.util.LinkedHashMap) values: [[sort:index, order:asc]]
Possible solutions: findAll(), findAll(groovy.lang.Closure), find(groovy.lang.Closure), getAll(java.util.List), getAll([Ljava.lang.Object;)
at grails.test.MockUtils.addDynamicFinders_closure56(MockUtils.groovy:641)
at myapp.MyService.getCards(MyService.groovy:8)
at myapp.MyServiceSpec.getCards returns empty map if no cards or statuses are available(MyServiceSpec.groovy:13)
Previously this test passed, but the failure occurred when I modified my Service to include sorting of results in the getThings()
method.
class MyService {
static transactional = true
static getThings() {
Thing.findAll(sort: 'index', order: 'asc')
}
}
This still appears to work when the application is run, so I suspect it's a limitation of the implementation of mockDomain()
.
class MyServiceSpec extends UnitSpec {
def 'mockDomain has some limits, i suspect'() {
given:
mockDomain(Thing)
def 开发者_开发知识库myService = new MyService()
when:
myService.getThings()
then:
true
}
}
So my question is are their differences in the methods added to a domain class using mockDomain()
as opposed to using the real domain class at runtime? If so, what are they?
sort
and order
are Hibernate criteria parameters, they won't work with MockDomain()
- it doesn't involve Hibernate. Luckily.
You can mock that findAll()
signature yourself, using instances array - the second parameter of MockDomain()
, (EDIT) like, this overrides findAll(Map)
signature of Thing
:
List<Thing> thingInstances = []
void setUp() {
mockDomain(Thing, thingInstances)
Thing.metaClass.`static`.findAll = { Map m ->
def result = thingInstances.sort{ it."${m.order}" }
m.order == 'asc' ? result : result.reverse()
}
}
(EDIT end)
Or you can make it integration test, then it will run for ages. Which I don't recommend.
There is a new approach for mocking domain objects: http://grails.1312388.n4.nabble.com/New-approach-to-mocking-domain-classes-in-Grails-unit-tests-td2529895.html. Maybe this helps you out here.
精彩评论