Results 1 to 8 of 8

Thread: MockHttpServletRequestBuilder is unable to accept non-String parameters

  1. #1

    Default 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. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    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[]).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3

    Default

    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.

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    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).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5

    Default

    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).

  6. #6
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    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.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  7. #7

    Default

    I sense condescension.

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

  8. #8
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    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...
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •