Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing 'Location' header of Spring REST Controller

After creating a resource in Spring REST Controller , I am returning it's location in header as below.

@RequestMapping(..., method = RequestMethod.POST)
public ResponseEntity<Void> createResource(..., UriComponentsBuilder ucb) {

    ...

    URI locationUri = ucb.path("/the/resources/")
        .path(someId)
        .build()
        .toUri();

    return ResponseEntity.created(locationUri).build();
}

In Unit Test, I am checking its location as below.

@Test
public void testCreateResource(...) {
    ...
    MockHttpServletRequestBuilder request = post("...")
        .content(...)
        .contentType(MediaType.APPLICATION_JSON)
        .accept(MediaType.APPLICATION_JSON);

    request.session(sessionMocked);

    mvc.perform(request)
        .andExpect(status().isCreated())
        .andExpect(header().string("Location", "/the/resources" + id);
}

This result cases fails with following message.

java.lang.AssertionError: Response header Location expected:</the/resources/123456> but was:<http://localhost/the/resources/123456>

Seems like I have to provide context prefix http://localhost for Location header in expectation.

  • Is it safe to hard code context? If so, why?
  • If not, what is right way to generate it correctly for test case?
like image 771
Bilal Mirza Avatar asked Dec 02 '16 11:12

Bilal Mirza


1 Answers

I'm guessing because you are using UriComponentsBuilder to build your URI it's setting the host name in your location header. Had you used something like just new URI("/the/resources"), your test would have passed.

In your case, I'd use redirectedUrlPattern to match the redirection URL:

.andExpect(redirectedUrlPattern("http://*/the/resources"))

This will match any hostname, so you don't have to hardcode localhost. Learn more about different patterns that you can use with AntPathMatcherhere.

like image 102
Suraj Bajaj Avatar answered Sep 18 '22 15:09

Suraj Bajaj