web-dev-qa-db-ja.com

MockMvc postメソッドを使用したSpring Controllerテスト

Spring Bootアプリケーションでコントローラーのメソッドをテストしようとしています。これはポストエンドポイントであり、リクエストで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");
}

}

このテストを実行すると、投稿リクエストが実行されますが、本文は空です:

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でリクエスト本文を設定するにはどうすればよいですか?

6
handris

.characterEncoding("utf-8"))を使用してみてください:

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

別のオプション(@ 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を使用していることに注意してください。

3
Slava Semushin

メソッドのパラメーターの注釈が確実に欠落しています。

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

次のようなものでなければなりません:

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

リクエストパラメータとして使用する場合。

Spring MVCのドキュメントはこちら をご覧ください。もちろん、テストの記述は、ここでidをどのように期待するかによって異なります。

0
galovics