Grails
  1. Grails
  2. GRAILS-7883

TestFor doesn't provide model property for controllers

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 2.0-M1
    • Fix Version/s: None
    • Component/s: Testing
    • Labels:
      None

      Description

      In Grails 2.0M1 controller unit tests using the new mixin approach don't seem to handle the controller's returned model correctly. The 'model' property provided by the mixin is always empty. For instance:

      class SomeController {
      def test()

      { [foo:"bar"] }

      }

      @TestFor(SomeController)
      class SomeControllerTests {
      def testModel()

      { controller.test() assert model.foo == "bar" // This fails as model is empty. }

      }

      Looking at the source of ControllerUnitTestMixin I see that it supplies the model like so:

      Map getModel() {
      final controller = webRequest.currentRequest.getAttribute(GrailsApplicationAttributes.CONTROLLER)
      return controller?.modelAndView?.model ?: [:]
      }

      Adding a bit of logging to my test demonstrates that the first line of that is fine and it gets the controller, but controller.modelAndView is null. And that's where my understanding of what's really going on runs out as I don't know how modelAnd View is supposed to come into being.

      Personally I think this is a showstopper and a bit of a surprise given it's covered in the 2.0M1 release notes complete with examples.

        Activity

        Hide
        Graeme Rocher added a comment -

        note you can workaround this by doing

        def model = controller.test()

        And then testing the returned map

        Show
        Graeme Rocher added a comment - note you can workaround this by doing def model = controller.test() And then testing the returned map
        Hide
        Graeme Rocher added a comment -

        The actual example from the documentation is this:

        // Test class
        class SimpleController {
            def home() {
                render view: "homePage", model: [title: "Hello World"]
            }
            ...
        }
        

        The render method populates the model and view. In the example provide you return the model explicitly from the method and should test the return value.

        Fixing this would involve weird proxying solutions that I am not sure are worth the added complexity

        Show
        Graeme Rocher added a comment - The actual example from the documentation is this: // Test class class SimpleController { def home() { render view: "homePage" , model: [title: "Hello World" ] } ... } The render method populates the model and view. In the example provide you return the model explicitly from the method and should test the return value. Fixing this would involve weird proxying solutions that I am not sure are worth the added complexity
        Hide
        Sam Carr added a comment -

        Actually the documentation I was looking at was section 1.1.5 of the G2.0M1 docs, which doesn't include the actual controller class definition, just the test (below). Looking just at that I had assumed that the test framework populated model for me, but I see that I am mistaken. The more detailed docs for Unit Testing in 9.1.1 do cover the whole example and make sense, especially now you've explained it. However an example where the controller just returns a model (which is most controllers in my experience) would be very helpful I think otherwise more people like me will run into confusion.

        @TestFor(SimpleController)
        class SimpleControllerTests {
        void testIndex()

        { controller.home() assert view == "/simple/homePage" assert model.title == "Hello World" }

        }

        Show
        Sam Carr added a comment - Actually the documentation I was looking at was section 1.1.5 of the G2.0M1 docs, which doesn't include the actual controller class definition, just the test (below). Looking just at that I had assumed that the test framework populated model for me, but I see that I am mistaken. The more detailed docs for Unit Testing in 9.1.1 do cover the whole example and make sense, especially now you've explained it. However an example where the controller just returns a model (which is most controllers in my experience) would be very helpful I think otherwise more people like me will run into confusion. @TestFor(SimpleController) class SimpleControllerTests { void testIndex() { controller.home() assert view == "/simple/homePage" assert model.title == "Hello World" } }

          People

          • Assignee:
            Graeme Rocher
            Reporter:
            Sam Carr
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Last Reviewed:

              Development