问题
I've put a very simple sample project on GitHub to reproduce the problem.
The main issue is that I have a PersonController
that has a PutMapping
to create a new person. In order to populate the Location
header with the URL to fetch that person, I add the UriComponentsBuilder
as parameter for that PutMapping
, as you can see here:
@PostMapping
public ResponseEntity<Person> add(@RequestBody final PersonForCreate personForCreate, UriComponentsBuilder uriComponentsBuilder) {
Person newPerson = new Person(this.people.size() + 1, personForCreate.getFirstName(), personForCreate.getLastName());
this.people.add(newPerson);
// create the URI for the "Location" header
MvcUriComponentsBuilder.MethodArgumentBuilder methodArgumentBuilder = MvcUriComponentsBuilder.fromMappingName(uriComponentsBuilder, "getById");
methodArgumentBuilder.arg(0, newPerson.getId());
URI uri = URI.create(methodArgumentBuilder.build());
return ResponseEntity.created(uri).body(newPerson);
}
This works fine when running the project. But when running a test this results in an IllegalArgumentException No WebApplicationContext
. The error comes from the MvcUriComponentsBuilder.fromMappingName
call, but I have no idea why.
My test looks as follows:
@ExtendWith(SpringExtension.class)
@WebMvcTest
class PersonControllerTest {
@Autowired
private PersonController personController;
@Test
void add() {
this.personController.add(new PersonForCreate("Charles", "Darwin"), UriComponentsBuilder.newInstance());
}
}
I'm not sure if passing UriComponentsBuilder.newInstance()
is correct, but I've tried with other values and notice no difference.
FYI, The sample project uses Spring Boot 2.2.3 and JUnit 5, but I have the same problem using a sample project on JUnit 4.
回答1:
Did you try MockMvc? The following code will be called in the same way HTTP request gets processed, as you're using @WebMvcTest, only the web layer is invoked rather than the whole context.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
@WebMvcTest
class PersonControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void add() throws Exception {
//this.personController.add(new PersonForCreate("Charles", "Darwin"), uriComponentsBuilder);
this.mockMvc.perform(MockMvcRequestBuilders.post("/person")
.content("{\"firstName\": \"Charles\",\"lastName\": \"Darwin\"}").contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isCreated())
.andExpect(MockMvcResultMatchers.content().string("{\"id\":4,\"firstName\":\"Charles\",\"lastName\":\"Darwin\"}"));
}
}
Spring.io/guides reference
https://spring.io/guides/gs/testing-web/
来源:https://stackoverflow.com/questions/59805642/uricomponentsbuilder-mvccomponentsbuilder-usage-in-a-spring-boot-test