Announcement Announcement Module
Collapse
No announcement yet.
MockHttpServletRequestBuilder is unable to accept non-String parameters Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • MockHttpServletRequestBuilder is unable to accept non-String parameters

    hi to everyone here,

    I am facing a roadblock in my mvc mock testing and I am hoping someone can provide me with some assistance.

    I am trying to perform a mock http POST with parameters. However, the .param() method can only accept String values.

    Code:
    String a = "a";
    int b = 10;
    
    this.mockMvc
    	.perform(
    		post("/service/somemethod")
    			.param("a", a)
    			.param("b", b) // flags as error
    	);
    Here's the implementation of somemethod()
    Code:
    @ModelAttribute(value = "response")
    @RequestMapping(value = "/somemethod", method = RequestMethod.POST)
    public MyResponse somemethod(@RequestParam String a, @RequestParam int b) {
    	return new MyResponse();
    }
    To make the test class compile, I had to make variable b into a String and change the method argument of int b to String b.
    Code:
    @ModelAttribute(value = "response")
    @RequestMapping(value = "/somemethod", method = RequestMethod.POST)
    public MyResponse somemethod(@RequestParam String a, @RequestParam String b) {
    	return new MyResponse();
    }
    So I dig further into MockHttpServletRequestBuilder.param():
    Code:
             private final MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
             ...
             ...
            /**
             * Add a request parameter to the {@link MockHttpServletRequest}.
             * If called more than once, the new values are added.
             *
             * @param name the parameter name
             * @param values one or more values
             */
            public MockHttpServletRequestBuilder param(String name, String... values) {
                    addToMultiValueMap(this.parameters, name, values);
                    return this;
            }
            ...
            ...
            private static <T> void addToMultiValueMap(MultiValueMap<String, T> map, String name, T[] values) {
                    Assert.hasLength(name, "'name' must not be empty");
                    Assert.notNull(values, "'values' is required");
                    Assert.notEmpty(values, "'values' must not be empty");
                    for (T value : values) {
                            map.add(name, value);
                    }
            }
    Upon inspecting the code in MockHttpServletRequestBuilder, I conclude it's not possible to use param with a non-String parameter. Also, it does not make sense to have a generic type method addToMultiValueMap and yet only accept String values. If that's the case, why bother having a generic type return for addToMultiValueMap?

    I don't want to change somemethod() argument b to String just because param() can't accept non-Strings. Is there any other way I can use mockMvc to post non-Strings?

    I am using 3.2.0.RELEASE.

    Thanks.

  • #2
    Which is logical... The web is all about strings, Spring takes care of converting the String into something else. So parameters are always Strings. Check the request.getParameter method that always returns a String (or String[]).

    Comment


    • #3
      What you are saying is that to use mockMvc, I have to convert all my @RequestParam arguments to String type? Thanks. I think I will use another testing approach. It seems that mockMvc is inadequate.

      Comment


      • #4
        No that is not what I'm saying...

        I'm saying that when using HTTP that that is only about Strings (hence my pointer to the HttpServletRequest getParameter method)... MockMvc uses springs infrastructure to convert those strings to the types you use in your request handling method (I strongly suggest you also read the reference guide).

        Comment


        • #5
          That's why I pasted code bits of the MockHttpServletRequestBuilder, to demonstrate that testing with mockMvc is limited with that it can only accept String parameters. No, MockMvc doesn't convert those strings to the types automatically (again refer to the code snippets I pasted above).

          Comment


          • #6
            Sigh...

            Strings go in, request is handled by spring which converts those strings to method arguments... I strongly suggest you read up on what Spring MVC does and what infrastructure components are involved.

            MockMVC handles the request in, more or less, the same way the dispatcher servlet does that and that means Strings go in and the infrastructure components are used to convert the input (all strings) to method arguments.

            Comment


            • #7
              I sense condescension.

              It's ok. I have already find other means of testing. Thanks for your input.

              Comment


              • #8
                No it is not condescension for some reason you refuse to take the fact that MockMVC is taking strings as input and lets the request handling over the spring infrastructure classes, just as the dispatcherservlet would do. MockMVC simply creates a HttpServletRequest (and Response) and the HttpServletRequest knowns only about Strings and as such MockMVC only accepts strings.

                As also mentioned a couple of times before the web is all about strings.

                MockMVC is for integration testing your controllers, this means including the spring infrastructure, if you just want to call the method to do a unit test then don't use MockMVC...

                Comment

                Working...
                X