如何测试使用标准查询(spock)的Grails服务? [英] How to test a Grails Service that utilizes a criteria query (with spock)?

查看:94
本文介绍了如何测试使用标准查询(spock)的Grails服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图测试一个简单的服务方法。该方法主要返回一个标准查询的结果,我希望测试它是否返回一个结果(取决于查询的内容)。

问题是,我不知道如何正确地进行相应的测试。我试图通过spock来实现它,但是用其他任何测试方法也是如此。



能否告诉我如何修改测试为了使它适用于手头的任务?



(顺便说一下,如果可能,我想保留它作为单元测试。)

>

EventService方法

  public HashSet< Event> ; listEventsForDate(Date date,int offset,int max){
date.clearTime()

def c = Event.createCriteria()
def results = c {
和{
le(startDate,date + 1)//今晚在午夜或之前开始?
ge(endDate,日期)//今天或晚些时候结束?
}
maxResults(max)
order(startDate,desc)
}
返回结果
}

Spock规范

 包myapp 

导入grails.plugin.spock。*
导入spock.lang。*

类EventServiceSpec extends Specification {

def event
def eventService = new EventService()

def setup(){
event = new Event()

event .publisher =模拟(用户)
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列出特定日期的事件(){
给出:事件的范围超过多天

时:我查了一个
def results = eventService.listEventsForDate(searchDate,0,100)

然后:事件被发现与否 - 取决于所请求的日期
numberOfResults == results.size()

其中:
searchDate | numberOfResults
新日期(2010,10,19)| 0 //前一天startDate
新日期(2010,10,20)| 1 //在startDate
新日期(2010,10,21)| 1 //在startDate
之后的一天新日期(2011,1,1)| 1 //在事件范围内的某一天
new Date(2011,3,6)| 1 //结束日期前一天
新日期(2011,3,7)| 1 //结束日期
新日期(2011,3,8)| 0 // endDate
}
}

错误

  groovy.lang.MissingMethodException:方法没有签名:static myapp.Event.createCriteria()is applicable对于参数类型:()values:[] 
at myapp.EventService.listEventsForDate(EventService.groovy:47)
at myapp.EventServiceSpec.list特定日期的事件(EventServiceSpec.groovy:29)


解决方案

您不应该使用单元测试来测试持久性 - 只是测试模拟框架。



相反,将标准查询移动到域类中相应命名的方法,并使用集成测试对数据库进行测试:

  class Event {
...
static Set< Event> findAllEventsByDay(Date date,int offset,int max){
...
}
}

class EventService {

Set<事件> listEventsForDate(Date date,int offset,int max){
...
return Event.findAllEventsByDay(date,offset,max)
}
}

如果将服务方法作为包装器仍然有价值(例如,如果它在数据库查询之上实现了一些业务逻辑) ,它现在很容易进行单元测试,因为它很容易模拟出静态域类方法调用:

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

这很合适,因为您正在测试服务如何使用它接收到的数据,检索在集成测试中涵盖。


I am trying to test a simple service method. That method mainly just returns the results of a criteria query for which I want to test if it returns the one result or not (depending on what is queried for).

The problem is, that I am unaware of how to right the corresponding test correctly. I am trying to accomplish it via spock, but doing the same with any other way of testing also fails.

Can one tell me how to amend the test in order to make it work for the task at hand?

(BTW I'd like to keep it a unit test, if possible.)

The EventService Method

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
}

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

解决方案

You should not use unit tests to test persistence - you're just testing the mocking framework.

Instead, move the criteria query to an appropriately named method in the domain class and test it against a database with an integration test:

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

If there's still value in having the service method as a wrapper (e.g. if it implements some business logic above and beyond the database query), it will now be easy to unit test since it's trivial to mock out the static domain class method call:

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

And that's appropriate since you're testing how the service uses the data it receives and assuming that the retrieval is covered in the integration tests.

这篇关于如何测试使用标准查询(spock)的Grails服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆