本文介绍了UriComponentsBuilder/MvcComponentsBuilder 在 Spring Boot 测试中的使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 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 测试中的使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!