2011-03-08 81 views
10

我想测试一个简单的服务方法。该方法主要是刚刚返回,我想测试条件查询的结果,如果它返回一个结果或不(这取决于中查询)。如何测试利用标准查询(spock)的Grails服务?

的问题是,我不知道如何正确地纠正相应的测试。我试图通过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 
} 

的斯波克规格

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) 

回答

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 } 

这就是恰当的,因为你测试如何e服务使用它接收到的数据并假定检索在集成测试中被覆盖。

4

单元测试不支持条件查询。从mockDomain documentation

[T]他的插件不支持模拟标准或HQL查询。如果您使用其中任何一种,只需手动模拟相应的方法(例如使用mockFor())或使用真实数据进行集成测试。

你必须让你的测试的集成测试。如果将测试从测试/单元文件夹移动到测试/集成文件夹,您会发现异常消失。

在单元测试中对标准支持做了一些工作,如果您觉得冒险,可以今天尝试一下。看到这个mailing list discussion of the DatastoreUnitTestMixin

相关问题