我正在尝试测试一种简单的服务方法。该方法主要只返回一个条件查询的结果,我想要测试它是否返回一个结果(取决于查询的内容)。
问题是,我不知道如何正确地对应相应的测试。我试图通过spock实现它,但是对任何其他测试方式做同样的事情也失败了。
可以告诉我如何修改测试以使其适用于手头的任务吗?
(顺便说一下,如果可能的话,我想把它作为单元测试。)
EventService方法
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
}
Spock规范
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
}
}
错误
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)
答案 0 :(得分:17)
您不应该使用单元测试来测试持久性 - 您只是在测试模拟框架。
相反,将条件查询移动到域类中适当命名的方法,并使用集成测试对数据库进行测试:
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)
}
}
如果将服务方法作为包装器仍然有价值(例如,如果它在数据库查询之上和之外实现了一些业务逻辑),那么现在很容易进行单元测试,因为模拟静态域类方法是微不足道的拨打:
def events = [new Event(...), new Event(...), ...]
Event.metaClass.static.findAllEventsByDay = { Date d, int offset, int max -> events }
这是合适的,因为您正在测试服务如何使用它接收的数据,并假设在集成测试中涵盖了检索。
答案 1 :(得分:4)
单元测试不支持Criteria查询。来自mockDomain documentation:
[T]他的插件不支持模拟标准或HQL查询。如果你使用其中任何一个,只需手动模拟相应的方法(例如使用mockFor())或使用与真实数据的集成测试。
您必须将测试作为集成测试。如果将测试从test / unit文件夹移动到test / integration文件夹,您将看到异常消失。
在单元测试中有一些关于标准支持的工作,如果你喜欢冒险,你今天就可以尝试一下。请参阅此mailing list discussion of the DatastoreUnitTestMixin。