【Spring】MockMVCでPOSTリクエストをテストする

MockMvcを使ってSpring MVCで作成したAPIに対してPOSTリクエストをテストする方法を紹介します。

実行環境は以下の通りです。

  • Java 11
  • Spring Boot 2.3.1

以下のようにMockHttpServletRequestBuilderのcontentメソッドにリクエストボディとなるJSON文字列を渡します。Content TypeはcontentTypeメソッドを使って指定します。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ItemControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void test1() throws Exception {

        var itemRequest = new ItemRequest(1, "test product", 100);
        var objectMapper = new ObjectMapper();
        mockMvc.perform(
                post("/items")
                .content(objectMapper.writeValueAsString(itemRequest))  // リクエストボディを指定
                .contentType(MediaType.APPLICATION_JSON_VALUE) // Content Typeを指定
        ).andExpect(status().isCreated());
    }
}

この例ではAPIのインターフェイスとなるコントローラとリクエストクラスを以下のように作成します。

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
public class ItemController {


    @ResponseStatus(HttpStatus.CREATED)
    @PostMapping("items")
    public ItemResponse save(@RequestBody ItemRequest itemRequest) {

        return new ItemResponse(itemRequest.getId(), itemRequest.getName(), itemRequest.getPrice());
    }
}

Lombokを使ってゲッター、セッター、コンストラクタなどを生成しています。

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ItemRequest {

    private int id;
    private String name;
    private int price;
}