【问题标题】:Spring Controller testing with MockMvc post method使用 MockMvc post 方法进行 Spring Controller 测试
【发布时间】:2018-04-21 13:22:29
【问题描述】:

我正在尝试在 Spring Boot 应用程序中测试我的控制器的方法。这是一个 post 端点,它在请求中获取一个 id 并将这个 id 传递给一个服务:

@Slf4j
@Controller
public class AdministrationController {

    private final AdministrationService administrationService;

    @Autowired
    public AdministrationController(AdministrationService administrationService) {
        this.administrationService = administrationService;
    }

    @PostMapping("/administration")
    public @ResponseBody ResponseEntity<String> deleteByMessageId(String id) {
        return new ResponseEntity<>(administrationService.deleteMessageById(id), HttpStatus.OK);
    }
}

控制器这个方法的测试:

RunWith(SpringRunner.class)
@WebMvcTest(AdministrationController.class)
public class AdministrationControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private AdministrationService service;

    @Test
    public void 
    deleteByMessageId_whenCalled_thenServiceMethodIsCalledWithRequestParameters() throws Exception {

        Object randomObj = new Object() {
            public final String id = "1234";
        };

        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(randomObj);


        MvcResult result = mvc.perform(
            post("/administration")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(json))
            .andExpect(status().isOk())
            .andReturn();

        verify(service, times(1)).deleteMessageById("1234");
}

}

当我运行这个测试时,post 请求被执行,但正文为空:

MockHttpServletRequest:
  HTTP Method = POST
  Request URI = /administration
   Parameters = {}
      Headers = {Content-Type=[application/json]}
         Body = <no character encoding set>
Session Attrs = {}

看来,即使我在测试中设置了内容,它也没有出现在我发送的请求中。 而且,确实,测试失败了:

Argument(s) are different! Wanted: "1234"
Actual invocation has different arguments: null

我在这里缺少什么?如何使用 MockMvc 设置请求正文?

【问题讨论】:

    标签: unit-testing spring-mvc spring-boot mockito mockmvc


    【解决方案1】:

    尝试使用.characterEncoding("utf-8"))

    MvcResult result = mvc.perform(post("/administration")
        .contentType(MediaType.APPLICATION_JSON)
        .content(json)
        .characterEncoding("utf-8"))
        .andExpect(status().isOk())
        .andReturn();
    

    【讨论】:

    • 顺序必须是characterEncoding, content, contentType
    • 你确定吗?我觉得没关系
    • 我似乎记得那个顺序对我的 IDE 很重要。我没有检查。但是这个命令确实有效。
    • 我想我知道 Lee Meador 来自哪里。排序无关紧要。问题是您的代码中某处有一个额外的括号,或者您缺少一个。 .andExpect() 在你关闭 mvc.perform() 之后出现。 .andExpect() 不会链接到 post()。刚刚刚好遇到这个问题。
    【解决方案2】:

    另一个选项(受@stelios-anastasakis 答案的启发)是在Content-Type 标头中提供字符编码:

    MvcResult result = mvc.perform(post("/administration")
        .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
        .content(json)
        .andExpect(status().isOk())
        .andReturn();
    

    请注意,我们在这里使用MediaType.APPLICATION_JSON_UTF8_VALUE 而不是MediaType.APPLICATION_JSON

    【讨论】:

    • APPLICATION_JSON_UTF8_VALUE 已弃用
    【解决方案3】:

    您肯定缺少方法参数的注释。

    public @ResponseBody ResponseEntity<String> deleteByMessageId(String id)
    

    应该是这样的:

    public @ResponseBody ResponseEntity<String> deleteByMessageId(@RequestParam("id") String id)
    

    如果您想将其用作请求参数。

    看看Spring MVC documentation here。 当然,编写测试取决于您对这里的 id 的期望。

    【讨论】:

      猜你喜欢
      • 2013-07-06
      • 2018-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-23
      • 2018-05-25
      • 1970-01-01
      • 2013-12-28
      相关资源
      最近更新 更多