为什么即使使用Spocks的Mock()模拟底层控制器,此方法仍返回null?

时间:2011-01-12 17:23:30

标签: unit-testing grails mocking grails-plugin spock

import grails.plugin.spock.*

class EventControllerSpec extends ControllerSpec {

    def "Creating a breadcrumb from an event"() {
        given: "I have a named event"
        def eventController = Mock(EventController)
        def event   = Mock(Event)
        event.title >> 'Space-Journey with Sprock and the Crew'
        event.title == 'Space-Journey with Sprock and the Crew'

        when: "I create a breadcrumb from it"
        def eventCrumb = eventController.createCrumb("Event", "show", "1", event.title)

        /*
        private Map createCrumb (String controllerName, String actionName, String id, String msg) {
        msg = (msg ? msg : "cr.breadcrumb.${controllerName}.${actionName}")
        [ 'controller':controllerName,
        'action':actionName,
        'id':id,
        'message':msg
        ]
         */

        then: "I receive a map where the message-value is the events' title"
        eventCrumb.message == event.title
    }
}

注意在EventController中注释掉的方法

  1. 为什么代码段导致“null对象上的无法获取属性”消息?“
  2. 如何正确设置代码段?
  3. 通常,在使用 Spock <时,我/将不需要任何 mockTagLib mockController mockLogging GrailsUnitTestCase函数/强>?

1 个答案:

答案 0 :(得分:1)

如果您正在对控制器进行单元测试,则会有一个约定,可以自动为您设置控制器。只需在测试中参考controller,如下所示;

import grails.plugin.spock.*

class EventControllerSpec extends ControllerSpec {

  def "Creating a breadcrumb from an event"() {
    given: "I have a named event"
    def event = Mock(Event)
    event.title >> 'Space-Journey with Sprock and the Crew'

    when: "I create a breadcrumb from it"
    def eventCrumb = controller.createCrumb("Event", "show", "1", event.title)

    /*
    private Map createCrumb (String controllerName, String actionName, String id, String msg) {
    msg = (msg ? msg : "cr.breadcrumb.${controllerName}.${actionName}")
    [ 'controller':controllerName,
    'action':actionName,
    'id':id,
    'message':msg
    ]
     */

    then: "I receive a map where the message-value is the events' title"
    eventCrumb.message == event.title
  }
}

您不需要显式模拟控制器,因为ControllerSpec为您执行此操作,但是,您可能需要模拟控制器正在使用的其他元素。有时通过控制器的元类

添加它们就足够了