Why is this method returning null even though the underlying controller is mocked using Spocks' Mock()?

StackOverflow https://stackoverflow.com/questions/4671828

문제

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

note the commented out method which is in the EventController

  1. Why does the snippet cause "Cannot get property 'message' on null object"?
  2. How can I setup the snippet correctly?
  3. Generally, will/won't I need any of the mockTagLib, mockController, mockLogging GrailsUnitTestCase functions when using Spock?
도움이 되었습니까?

해결책

If you are unit testing a controller there is a convention which automatically sets the controller up for you. Just refer to the controller in your test as follows;

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

You don't need to explicitly mock the controller as ControllerSpec does it for you, however, you may need to mock other elements that your controller is using. Sometimes it is sufficient to add these through the controller's metaclass

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top