Affects: spring-boot-starter-test 2.1.6.RELEASE
Use Case: When performing an spring integration test over a get controller we add an url as a String to MockHttpServletRequestBuilder to perform such action.
Issue: When we add that url String without the protocol (for instance: "localhost:port...") the request returns a NullPointerException.
Code failing:
MockHttpServletResponse response =
mockMvc.perform(MockMvcRequestBuilders.get("localhost:port/some domain/etc...")).andReturn().getResponse();
Code working:
MockHttpServletResponse response =
mockMvc.perform(MockMvcRequestBuilders.get("http://localhost:port/some domain/etc...")).andReturn().getResponse();
Just to clarify the only difference is that the second url contains the http protcol explicitly declared
Expectation: Since http is the default protocol in many other frameworks I expect it to be inferred as url protocl if no other is defined explicitly.
Cause:
Inside that MockMvcRequestBuilders.get("uri") method there is a call to a private constructor who converts that String into an actual URI
MockHttpServletRequestBuilder(HttpMethod httpMethod, String url, Object... vars) {
this(httpMethod.name(), UriComponentsBuilder.fromUriString(url).buildAndExpand(vars).encode().toUri());
}
But it does not work properly since this.utl.getRawPath() returns null which later causes updatePathRequestProperties to throw mentioned NullPointerException
Thanks in advance!
Comment From: rstoyanchev
MockMvcRequestBuilders uses UriComponentsBuilder.fromUriString, which can't parse the given input correctly because "localhost:" looks like a scheme.
Switching to UriComponentsBuilder.fromHttpUrl provides a more helpful error:
java.lang.IllegalArgumentException: [localhost:8080/path] is not a valid HTTP URL
I don't we should go further and fill in the protocol since we don't know if that should be "http:" or "https:" and that could lead to surprises, and possibly even possible contradictions (e.g. "localhost:443").
Comment From: rstoyanchev
Actually it looks like fromUriString is quite useful because it allows to provide a path only. We need to keep that so it comes down to, either provide a URI with a path only (i.e. no scheme, host, port), or otherwise a proper HTTP URL.
If you want shorter, why not skip the host and port too?