UriComponentsBuilder/MvcComponentsBuilder 在 Spring 启动测试中的用法
UriComponentsBuilder/MvcComponentsBuilder usage in a Spring Boot Test
我已经放了一个非常简单的 sample project on GitHub 来重现问题。
主要问题是我有一个 PersonController
有一个 PutMapping
来创建一个新人。为了用 URL 填充 Location
header 来获取那个人,我添加 UriComponentsBuilder
作为 PutMapping
的参数,如您在此处看到的:
@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);
}
这在 运行 项目时工作正常。但是当 运行 测试时,这会导致 IllegalArgumentException No WebApplicationContext
。错误来自 MvcUriComponentsBuilder.fromMappingName
调用,但我不知道为什么。
我的测试如下:
@ExtendWith(SpringExtension.class)
@WebMvcTest
class PersonControllerTest {
@Autowired
private PersonController personController;
@Test
void add() {
this.personController.add(new PersonForCreate("Charles", "Darwin"), UriComponentsBuilder.newInstance());
}
}
我不确定传递 UriComponentsBuilder.newInstance()
是否正确,但我尝试使用其他值并没有发现差异。
仅供参考,示例项目使用 Spring Boot 2.2.3 和 JUnit 5,但我在 JUnit 4 上使用示例项目时遇到同样的问题。
你试过 MockMvc 了吗?当您使用@WebMvcTest 时,将以处理 HTTP 请求的相同方式调用以下代码,仅调用 Web 层而不是整个上下文。
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参考
我已经放了一个非常简单的 sample project on GitHub 来重现问题。
主要问题是我有一个 PersonController
有一个 PutMapping
来创建一个新人。为了用 URL 填充 Location
header 来获取那个人,我添加 UriComponentsBuilder
作为 PutMapping
的参数,如您在此处看到的:
@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);
}
这在 运行 项目时工作正常。但是当 运行 测试时,这会导致 IllegalArgumentException No WebApplicationContext
。错误来自 MvcUriComponentsBuilder.fromMappingName
调用,但我不知道为什么。
我的测试如下:
@ExtendWith(SpringExtension.class)
@WebMvcTest
class PersonControllerTest {
@Autowired
private PersonController personController;
@Test
void add() {
this.personController.add(new PersonForCreate("Charles", "Darwin"), UriComponentsBuilder.newInstance());
}
}
我不确定传递 UriComponentsBuilder.newInstance()
是否正确,但我尝试使用其他值并没有发现差异。
仅供参考,示例项目使用 Spring Boot 2.2.3 和 JUnit 5,但我在 JUnit 4 上使用示例项目时遇到同样的问题。
你试过 MockMvc 了吗?当您使用@WebMvcTest 时,将以处理 HTTP 请求的相同方式调用以下代码,仅调用 Web 层而不是整个上下文。
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参考