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でリクエスト本文を設定するにはどうすればよいですか?
.characterEncoding("utf-8"))
を使用してみてください:
MvcResult result = mvc.perform(post("/administration")
.contentType(MediaType.APPLICATION_JSON)
.content(json)
.characterEncoding("utf-8"))
.andExpect(status().isOk())
.andReturn();
別のオプション(@ 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
を使用していることに注意してください。
メソッドのパラメーターの注釈が確実に欠落しています。
public @ResponseBody ResponseEntity<String> deleteByMessageId(String id)
次のようなものでなければなりません:
public @ResponseBody ResponseEntity<String> deleteByMessageId(@RequestParam("id") String id)
リクエストパラメータとして使用する場合。
Spring MVCのドキュメントはこちら をご覧ください。もちろん、テストの記述は、ここでidをどのように期待するかによって異なります。