问题描述
我在 GitHub 上放了一个非常简单的示例项目来重现问题.
I've put a very simple sample project on GitHub to reproduce the problem.
主要问题是我有一个 PersonController
有一个 PutMapping
来创建一个新人.为了使用 URL 填充 Location
标头以获取该人,我添加了 UriComponentsBuilder
作为该 PutMapping
的参数,如您所见这里:
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);
}
这在运行项目时工作正常.但是在运行测试时,这会导致 IllegalArgumentException No WebApplicationContext
.错误来自 MvcUriComponentsBuilder.fromMappingName
调用,但我不知道为什么.
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.
我的测试如下:
@ExtendWith(SpringExtension.class)
@WebMvcTest
class PersonControllerTest {
@Autowired
private PersonController personController;
@Test
void add() {
this.personController.add(new PersonForCreate("Charles", "Darwin"), UriComponentsBuilder.newInstance());
}
}
我不确定传递 UriComponentsBuilder.newInstance()
是否正确,但我尝试了其他值并没有发现任何区别.
I'm not sure if passing UriComponentsBuilder.newInstance()
is correct, but I've tried with other values and notice no difference.
仅供参考,示例项目使用 Spring Boot 2.2.3 和 JUnit 5,但我在 JUnit 4 上使用示例项目时遇到了同样的问题.
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.
推荐答案
您是否尝试过 MockMvc?以下代码将以与处理 HTTP 请求相同的方式调用,因为您使用的是 @WebMvcTest,仅调用 Web 层而不是整个上下文.
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 参考
Spring.io/guides reference
https://spring.io/guides/gs/testing-web/一个>
这篇关于UriComponentsBuilder/MvcComponentsBuilder 在 Spring Boot 测试中的使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!