2011-03-08 20 views
10

Sto provando a testare un metodo di servizio semplice. Questo metodo restituisce principalmente i risultati di una query di criteri per cui voglio test se restituisce il risultato o non (a seconda di cosa è richiesto).Come testare un servizio Grails che utilizza una query di criteri (con spock)?

Il problema è che non sono a conoscenza di come correggere correttamente il test corrispondente. Sto cercando di ottenerlo tramite spock, ma anche fare lo stesso con qualsiasi altro modo di test fallisce.

Si può dirmi come modificare il test per farlo funzionare per l'attività in corso?

(BTW mi piacerebbe tenerlo un test di unità, se possibile.)

Il Metodo 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 
} 

Lo 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) 

risposta

17

Non si dovrebbero usare i test unitari per testare la persistenza - si sta solo testando la struttura di derisione.

Invece, spostare la query criteri per un metodo di nome appropriato nella classe di dominio e testarlo su un database con un test di integrazione:

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) 
    } 
} 

Se c'è ancora un valore ad avere il metodo di servizio come un wrapper (ad esempio, se si implementa una logica di business sopra e al di là della query di database), ora sarà facile da test di unità dal momento che è banale per deridere il metodo statico della classe di dominio chiamata:

def events = [new Event(...), new Event(...), ...] 
Event.metaClass.static.findAllEventsByDay = { Date d, int offset, int max -> events } 

e questo è appropriato dato che siete testare come Il servizio utilizza i dati che riceve e presuppone che il recupero sia coperto nei test di integrazione.

4

Le query di criteri non sono supportate nei test di unità. Da mockDomain documentation:

[T] Il plug-in non supporta la simulazione di criteri o query HQL. Se si utilizza uno di questi, basta prendere in giro i metodi corrispondenti manualmente (ad esempio con mockFor()) o utilizzare un test di integrazione con dati reali.

Dovrai rendere il test un test di integrazione. Vedrai che l'eccezione scompare se sposti il ​​test dalla cartella test/unità alla cartella test/integrazione.

C'è un po 'di lavoro sul supporto dei criteri nei test unitari, e se ti senti avventuroso, puoi provarlo oggi. Vedi questo mailing list discussion of the DatastoreUnitTestMixin.

Problemi correlati