Creating a mock HttpServletRequest out of a url string?

I have a service that does some work on an HttpServletRequest object, specifically using the request.getParameterMap and request.getParameter to construct an object.

I was wondering if there is a straightforward way to take a provided url, in the form of a string, say

String url = "http://www.example.com/?param1=value1&param";

and easily convert it to a HttpServletRequest object so that I can test it with my unit tests? Or at least just so that request.getParameterMap and request.getParameter work correctly?

131136 次浏览

Spring has MockHttpServletRequest in its spring-test module.

If you are using maven you may need to add the appropriate dependency to your pom.xml. You can find spring-test at mvnrepository.com.

You would generally test these sorts of things in an integration test, which actually connects to a service. To do a unit test, you should test the objects used by your servlet's doGet/doPost methods.

In general you don't want to have much code in your servlet methods, you would want to create a bean class to handle operations and pass your own objects to it and not servlet API objects.

Simplest ways to mock an HttpServletRequest:

  1. Create an anonymous subclass:

    HttpServletRequest mock = new HttpServletRequest ()
    {
    private final Map<String, String[]> params = /* whatever */
    
    
    public Map<String, String[]> getParameterMap()
    {
    return params;
    }
    
    
    public String getParameter(String name)
    {
    String[] matches = params.get(name);
    if (matches == null || matches.length == 0) return null;
    return matches[0];
    }
    
    
    // TODO *many* methods to implement here
    };
    
  2. Use jMock, Mockito, or some other general-purpose mocking framework:

    HttpServletRequest mock = context.mock(HttpServletRequest.class); // jMock
    HttpServletRequest mock2 = Mockito.mock(HttpServletRequest.class); // Mockito
    
  3. Use HttpUnit's ServletUnit and don't mock the request at all.

Here it is how to use MockHttpServletRequest:

// given
MockHttpServletRequest request = new MockHttpServletRequest();
request.setServerName("www.example.com");
request.setRequestURI("/foo");
request.setQueryString("param1=value1&param");


// when
String url = request.getRequestURL() + '?' + request.getQueryString(); // assuming there is always queryString.


// then
assertThat(url, is("http://www.example.com:80/foo?param1=value1&param"));

for those looking for a way to mock POST HttpServletRequest with Json payload, the below is in Kotlin, but the key take away here is the DelegatingServetInputStream when you want to mock the request.getInputStream from the HttpServletRequest

@Mock
private lateinit var request: HttpServletRequest


@Mock
private lateinit var response: HttpServletResponse


@Mock
private lateinit var chain: FilterChain


@InjectMocks
private lateinit var filter: ValidationFilter




@Test
fun `continue filter chain with valid json payload`() {
val payload = """{
"firstName":"aB",
"middleName":"asdadsa",
"lastName":"asdsada",
"dob":null,
"gender":"male"
}""".trimMargin()


whenever(request.requestURL).
thenReturn(StringBuffer("/profile/personal-details"))
whenever(request.method).
thenReturn("PUT")
whenever(request.inputStream).
thenReturn(DelegatingServletInputStream(ByteArrayInputStream(payload.toByteArray())))


filter.doFilter(request, response, chain)


verify(chain).doFilter(request, response)
}