Announcement Announcement Module
Collapse
No announcement yet.
spring-mvc-test How to set @ModelAttribute value on mocked POST ? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • spring-mvc-test How to set @ModelAttribute value on mocked POST ?

    I have a controller.. with the following method

    Code:
      @RequestMapping(value = "create", method = RequestMethod.POST)
        public ModelAndView createUser(@ModelAttribute("user") MyUser user, BindingResult result, Principal principal) {
    
      // ... do stuff with user 
    
    }
    
    In the test I use
    
        MyUser user = new MyUser;
        MockMvcBuilders.standaloneSetup(controller).build().
                    perform(post("/foo/create").requestAttr("user", user)
    When the controller method is invoked - the MyUser instance passed in the parameter associated with the @ModelAttribute parameter - is *not* the instance I placed in the requestAttr in the test. So I don't see the properties I expect to see as provided by a post of a form.

    Is this the correct way to do this ?

    TIA.
    Last edited by dvb123; Mar 9th, 2012, 02:55 AM.

  • #2
    A @ModelAttribute != a request attribute... I suggest a read of the spring reference guide on this.

    It is either constructed by the method itself by calling the default constructor, created from a method annotated with @ModelAttribute or retrieved from the session if used in combination with a @SessionAttributes.

    And for what I know the spring-mvc-test honours this...

    Comment


    • #3
      Originally posted by Marten Deinum View Post
      A

      And for what I know the spring-mvc-test honours this...
      Doesn't appear to. Hence the question.

      See org.springframework.test.web.server.request.Defaul tRequestBuilder

      There appears to be no way to bind some test object to the method parameter annotated with @ModelAttribute

      I've looked at how this works already in org.springframework.web.servlet.mvc.method.annotat ion.RequestMappingHandlerAdapter

      I don't really want to develop an in depth understanding of the internals of all this - just want to understand how to use 'spring-mvc-test' giving its being plugged on InfoQ at the moment, so giving it a whirl.

      :-)

      Comment


      • #4
        There is no way because it also doesn't work that way inside the RequestMappingHandlerAdapter (as I tried to explain).

        There appears to be no way to bind some test object to the method parameter annotated with @ModelAttribute
        Correct, as that isn't the way Spring MVC works.

        The invocation still passes through the HandlerAdapter so either

        1. Use @SessionAttributes which allows you to add a session attribute
        2. Define a @ModelAttribute annotated method which will be invoked before the actual request handling method
        3. It is constructed for the request using the default constructor.

        As Spring-Mvc-Test used the internal @MVC infrastructure to call the methods.

        In option 1 and 2 there is a change to use a "passed in" instance, for the @SessionAttribute define make it a session attribute for the method (and hopefully that calls a dao) use a stub or mocked dao which returns your predefined object...

        Also not sure what you want to test but after invocation your model (should) contain an MyUser object which you can verify.
        Last edited by Marten Deinum; Mar 8th, 2012, 09:18 AM.

        Comment


        • #5
          Thank you Marten. I could not see any way RequestMappingHandlerAdapter would do this. We already do have @ModelAttribute annotated methods in the controller, but here I do not wish to do that. I was just seeking confirmation that it could not be done.

          :-)

          Will try your suggestions.

          Comment


          • #6
            I've now resolved this to do what I wanted. I have to confess I had not expressed my original question very well.
            What I was trying to do was not pass in a specific instance of a POJO as part of the test, but to simulate form parameters being provided to the controller and resulting in the expected properties on the object being set. I.e. verify the binding of the parameters into the object annotated with @ModelAttribute. I know it is questionable whether to test for this - but the intention was just to understand how to use MockMvc having watched the presentation on it.

            So this is what "fixed" what I was trying to achieve. Just use .param(). Slightly embarrassing - but sharing in case it helps others.

            Code:
               
             
                    MockMvcBuilders.standaloneSetup(controller).build()
                            .perform(post("/foo/create").param("username", "userxyz").param("password", "xyz"))

            Comment


            • #7
              What I was trying to do was not pass in a specific instance of a POJO as part of the test
              Judging from your questions and your approach that was exactly what you where trying to do?!

              However what you have now is basically what you need to do if it is useful to only test the binding (I would simply trust this to work) is another question/debate...

              Comment


              • #8
                Originally posted by Marten Deinum View Post
                Judging from your questions and your approach that was exactly what you where trying to do?!
                No. I wasn't.

                As I've said - I was wishing to replicate the form parameters being passed from the test code & appearing in the object - *not* same instance. I've also said that

                I know it is questionable whether to test for this ...
                It was just a quick shake down of spring-mvc-test. That is the perspective of all this.

                I don't see the point in disputing what is in my head, my wife already expends enough effort in that area already.

                I didn't understand fully how the binding into @ModelAttribute worked yesterday morning - now I do having been through the source. Hence my position has altered from my originally posted question.

                Comment


                • #9
                  Originally posted by dvb123 View Post
                  Code:
                     
                   
                          MockMvcBuilders.standaloneSetup(controller).build()
                                  .perform(post("/foo/create").param("username", "userxyz").param("password", "xyz"))
                  Thanks for that hint saved me a lot of time to find an answer.

                  Did anyone know, if there is another solution right now ?

                  Comment


                  • #10
                    Hi all - I am new to MockMvc, and trying to send object as a ModelAttribute using POST. UploadData is a java bean.

                    My controller has following -
                    @RequestMapping(value = "/test.do", method = RequestMethod.POST)
                    public String loadTemplateDataHandler1(@ModelAttribute("uploadDa ta") UploadData uploadData,
                    BindingResult result,
                    ModelMap model,
                    HttpServletRequest request){
                    System.out.println("Upload date "+ uploadData.getUploadDate()); //this returns java.uti.Date
                    return "testing";
                    }


                    My test case is following -
                    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).alway sExpect(status().isOk()).build();

                    However, I am not sure how to set java.util.Date object on UploadData object from my test

                    Any help would be much appreciated.

                    cheers

                    this.mockMvc.perform( post("/test.do"));

                    Comment

                    Working...
                    X