2011-03-08 18 views
10

Estoy tratando de probar un método de servicio simple. Ese método principalmente solo devuelve los resultados de una consulta de criterio para la cual deseo probar si devuelve el resultado o no (dependiendo de lo que se solicita).¿Cómo probar un servicio de Grails que utiliza una consulta de criterios (con spock)?

El problema es que no sé cómo corregir la prueba correspondiente correctamente. Estoy tratando de lograrlo a través de Spock, pero hacer lo mismo con cualquier otra forma de prueba también falla.

¿Puede uno decirme cómo modificar la prueba para que funcione para la tarea en cuestión?

(Por cierto que me gustaría mantener una prueba de unidad, si es posible.)

El Método 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 
} 

La especificación 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 
    } 
} 

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

Respuesta

17

No debe usar pruebas unitarias para probar la persistencia; solo está probando el marco de burla.

En su lugar, mover la consulta criterios de un método apropiado nombre de la clase de dominio y probarlo en contra de una base de datos con una prueba de integración:

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

Si todavía hay valor en tener el método de servicio como un contenedor (por ejemplo, si se implementa una lógica de negocio más allá de la consulta de base de datos), que ahora va a ser fácil de probar la unidad, ya que es trivial para burlarse a cabo el método de la clase de dominio estático llamada:

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

y eso es apropiado, ya que está probando cómo th El servicio utiliza los datos que recibe y supone que la recuperación está cubierta en las pruebas de integración.

4

Las preguntas de los criterios no se admiten en las pruebas unitarias. Del mockDomain documentation:

[T] el complemento no admite la burla de criterios o consultas HQL. Si usa cualquiera de estos, simplemente haga una burla manual de los métodos correspondientes (por ejemplo, con mockFor()) o use una prueba de integración con datos reales.

Tendrás que hacer que tu prueba sea una prueba de integración. Verá que la excepción desaparece si traslada la prueba de la carpeta de prueba/unidad a la carpeta de prueba/integración.

Se está trabajando en el soporte de criterios en pruebas unitarias, y si te sientes aventurero, puedes probarlo hoy mismo. Vea esto mailing list discussion of the DatastoreUnitTestMixin.

Cuestiones relacionadas