I am trying to test a simple service method. That method mainly just returns the results of a criteria query for which I want to test if it returns the one result or not (depending on what is queried for).
The problem is, that I am unaware of how to right the corresponding test correctly. I am trying to accomplish it via spock, but doing the same with any other way of testing also fails.
Can one tell me how to amend the test in order to make it work for the task at hand?
(BTW I'd like to keep it a unit test, if possible.)
The EventService Method
public HashSet<Event> listEventsForDate(Date date, int offset, int max) {
date.clearTime()
def c = Event.createCriteria()
def results = c {
and {
le("startDate", date+1) // starts tonight at midnight or prior?
ge("endDate", date) // ends today or later?
}
maxResults(max)
order("startDate", "desc")
}
return results
}
The Spock Specification
package myapp
import grails.plugin.spock.*
import spock.lang.*
class EventServiceSpec extends Specification {
def event
def eventService = new EventService()
def setup() {
event = new Event()
event.publisher = Mock(User)
event.title = 'et'
event.urlTitle = 'ut'
event.details = 'details'
event.location = 'location'
event.startDate = new Date(2010,11,20, 9, 0)
event.endDate = new Date(2011, 3, 7,18, 0)
}
def "list the Events of a specific date"() {
given: "An event ranging over multiple days"
when: "I look up a date for its respective events"
def results = eventService.listEventsForDate(searchDate, 0, 100)
then: "The event is found or not - depending on the requested date"
numberOfResults == results.size()
where:
searchDate | numberOfResults
new Date(2010,10,19) | 0 // one day before startDate
new Date(2010,10,20) | 1 // at startDate
new Date(2010,10,21) | 1 // one day after startDate
new Date(2011, 1, 1) | 1 // someday during the event range
new Date(2011, 3, 6) | 1 // one day before endDate
new Date(2011, 3, 7) | 1 // at endDate
new Date(2011, 3, 8) | 0 // one day after endDate
}
}
The Error
groovy.lang.MissingMethodException: No signature of method: static myapp.Event.createCriteria() is applicable for argument types: () values: []
at myapp.EventService.listEventsForDate(EventService.groovy:47)
at myapp.EventServiceSpec.list the Events of a specific date(EventServiceSpec.groovy:29)
You should not use unit tests to test persistence - you're just testing the mocking framework.
Instead, move the criteria query to an appropriately named method in the domain class and test it against a database with an integration test:
class Event {
...
static Set<Event> findAllEventsByDay(Date date, int offset, int max) {
...
}
}
class EventService {
Set<Event> listEventsForDate(Date date, int offset, int max) {
...
return Event.findAllEventsByDay(date, offset, max)
}
}
If there's still value in having the service method as a wrapper (e.g. if it implements some business logic above and beyond the database query), it will now be easy to unit test since it's trivial to mock out the static domain class method call:
def events = [new Event(...), new Event(...), ...]
Event.metaClass.static.findAllEventsByDay = { Date d, int offset, int max -> events }
And that's appropriate since you're testing how the service uses the data it receives and assuming that the retrieval is covered in the integration tests.
Criteria queries are not supported in unit tests. From the mockDomain documentation:
[T]he plugin does not support the mocking of criteria or HQL queries. If you use either of those, simply mock the corresponding methods manually (for example with mockFor() ) or use an integration test with real data.
You'll have to make your test an integration test. You'll see that the exception goes away if you move the test from the test/unit folder to the test/integration folder.
There is some work being done on criteria support in unit tests, and if you're feeling adventurous, you can try it out today. See this mailing list discussion of the DatastoreUnitTestMixin.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With