Issue
I'm trying to test my Rest controllers from my Spring Boot application and want the controllers to be available under the same path as in production.
For example I have the following Controller:
@RestController
@Transactional
public class MyController {
private final MyRepository repository;
@Autowired
public MyController(MyRepository repository) {
this.repository = repository;
}
@RequestMapping(value = "/myentity/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Resource<MyEntity>> getMyEntity(
@PathVariable(value = "id") Long id) {
MyEntity entity = repository.findOne(id);
if (entity == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(entity, HttpStatus.OK);
}
}
Within my application.yml
I have configured the context path for the application:
server:
contextPath: /testctx
My test for this controller looks as follows:
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = MyController.class, secure=false)
public class MyControllerTest {
@Autowired
private MyRepository repositoryMock;
@Autowired
private MockMvc mvc;
@Test
public void testGet() throws Exception {
MyEntity entity = new MyEntity();
entity.setId(10L);
when(repositoryMock.findOne(10L)).thenReturn(entity);
MockHttpServletResponse response = this.mvc.perform(
MockMvcRequestBuilders.get("/testctx/myentity/10"))
.andReturn().getResponse();
assertEquals(response.getStatus(), 200);
}
@TestConfiguration
public static class TestConfig {
@Bean
MyRepository mockRepo() {
return mock(MyRepository.class);
}
}
}
This test fails since the status code is 404 for the call. If I call /myentity/10
it works. Unfortunately the rest call is initiated by a CDC-Test-Framework (pact) so I cannot change the requested path (containing the context path /testctx
). So is there a way to tell spring boot test to start the rest endpoint with a defined context path also during testing?
Solution
You could try:
@WebMvcTest(controllers = {MyController.class})
@TestPropertySource(locations="classpath:application.properties")
class MyControllerTest {
@Autowired
protected MockMvc mockMvc;
@Value("${server.servlet.context-path}")
private String contextPath;
@BeforeEach
void setUp() {
assertThat(contextPath).isNotBlank();
((MockServletContext) mockMvc.getDispatcherServlet().getServletContext()).setContextPath(contextPath);
}
protected MockHttpServletRequestBuilder createGetRequest(String request) {
return get(contextPath + request).contextPath(contextPath)...
}
Answered By - mwerlitz