UriComponentsBuilder/MvcComponentsBuilder usage in a Spring Boot Test

橙三吉。 提交于 2021-01-29 09:21:38

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!