2011-03-18 9 views
7

que he escrito el siguiente controlador de Grailsdatos de prueba Grails unión

class CategoryController { 

    def create = { 
     def newCategory = new CategoryCommand() 
     bindData(newCategory, params) 
     [newCategory: newCategory] 
    } 
} 

class CategoryCommand { 

    String name 
    String seoName 
} 

He escrito esta prueba de la unidad para probar el enlace de datos:

class CategoryControllerTests extends ControllerUnitTestCase { 


    void testCreate() { 

     // A new ControllerCommand should be returned if invoked with no params 
     assertNotNull controller.create() 

     // If called with params, they should be bound 
     mockParams.name = 'snooker' 
     mockParams.seoName = 'snooker-loopy' 
     def model = controller.create() 

     CategoryCommand newCategory = model.newCategory 
     assertEquals 'snooker', newCategory.name 
     assertEquals 'snooker-loopy', newCategory.seoName 

    } 
} 

pero me da esta excepción cuando es controller.create() invocado:

Ninguna firma del método: com.example.CategoryController.bindData() es aplicable para tipos de argumentos: (com.e xample.CategoryCommand, valores) org.codehaus.groovy.grails.web.taglib.GroovyPageAttributes: [[email protected], [:]]

Intenté funcionar esto como una prueba de integración en su lugar, pero El resultado es el mismo.

Respuesta

6

derecho ... me hizo un poco de excavación, y se encontró this blog page que dice (a mitad de camino hacia abajo):


nota: no ControllerUnitTestCase apoyo de algún método dinámico. Para instancia: bindData(). Entonces es mejor las pruebas de integración uso, o puede añadir este método para el regulador:

this.controller.metaClass.bindData = { obj, params -> 
    params.each { key, value -> 
    obj."$key" = value 
    } 
} 

O, que tenía un aspecto en el Grails source code, y para burlarse de él a hacer lo mismo as what Grails does, Creo que tendríamos que hacer:

import org.codehaus.groovy.grails.web.metaclass.BindDynamicMethod 

this.controller.metaClass.bindData = { obj, params -> 
    new BindDynamicMethod().invoke(delegate, BindDynamicMethod.BIND_DATA_METHOD, [ obj, params ] as Object[]) ; 
} 

(creo - No se ha probado que aunque)

+0

estoy usando Grails 1.3.6 y no parece ser un campo 'BindDynamicMethod.BIND_DATA_METHOD', por lo que el segundo fragmento de código no funciona. Los enlaces que proporcionó no están funcionando en este momento, por lo que no puedo ver dónde obtuvo esto en –

+0

El primer fragmento de código tiene el inconveniente de volver a implementar en el código de prueba exactamente lo que intento probar, es decir, vinculación de datos –

0

Aquí hay dos soluciones posibles:

  1. Intente ejecutarlo como una prueba de integración de nuevo. ;) Moví tu clase de prueba a la carpeta de prueba/integración y pasó por mí. También estoy ejecutando Grails 1.3.6.

  2. Cambie su controlador para no utilizar bindData. Esta acción del controlador es equivalente a lo que tenemos ahora, y va a pasar su prueba de unidad:

    def create = { 
        def newCategory = new CategoryCommand(params) 
        [newCategory: newCategory] 
    } 
    

    único inconveniente es que sólo BindData puede enlazar datos de objetos asociados, si usted tiene un nombre de parámetro como "myAssociation. mi propiedad".

3

Como se mencionó anteriormente, imitando a Grails mediante el uso de BindDynamicMethod funciona. Esto funciona para mí en Grails 1.3.5:

import org.codehaus.groovy.grails.web.metaclass.BindDynamicMethod 

protected void setUp() { 
    def mc = controller.class.metaClass 
    def bind = new BindDynamicMethod() 
    mc.bindData = { Object target, Object args -> 
     bind.invoke(delegate, "bindData", [ target, args ] as Object[]) 
    } 
    mc.bindData = { Object target, Object args, List disallowed -> 
     bind.invoke(delegate, "bindData", [ target, args, [ exclude: disallowed ]] as Object[]) 
    } 
    mc.bindData = { Object target, Object args, List disallowed, String filter -> 
     bind.invoke(delegate, "bindData", [ target, args, [ exclude: disallowed ], filter ] as Object[]) 
    } 
    mc.bindData = { Object target, Object args, Map includeExclude -> 
     bind.invoke(delegate, "bindData", [ target, args, includeExclude ] as Object[]) 
    } 
    mc.bindData = { Object target, Object args, Map includeExclude, String filter -> 
     bind.invoke(delegate, "bindData", [ target, args, includeExclude, filter ] as Object[]) 
    } 
    mc.bindData = { Object target, Object args, String filter -> 
     bind.invoke(delegate, "bindData", [ target, args, filter ] as Object[]) 
    } 

} 

Esto se copia de org/codehaus/groovy/grails/plugins/web/ControllersGrailsPlugin.groovy, por lo que es compatible con todas las formas de bindData.

Esperemos que la situación mejore con los próximos Grails 1.4 y testing mixins.

+0

Agradable ver esta implementación como mixin: [Controlar las acciones del controlador Grails que utilizan el método bindData] (http://www.jworks.nl/2011/08/03/testing-grails-controllers/) –

Cuestiones relacionadas