2011-03-08 80 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

相關問題