spring.svg

【Spring Boot】JUnit 5を用いたテストの基本

SpringBoot

JUnit 5 の基本

この記事では、REST API に対して JUnit 5 を用いたテストを想定しています。 JUnit 5 の基本は、こちらの記事を参考にしてください。

@SpringBootTest

@SpringBootTestは、Spring Boot の機能を用いる処理のテストを行う場合に、付与するアノテーションです。 主に、Service や Dao(Repository)など DI コンテナを用いた処理をテストする際に使用します。

@SpringBootTest
public class SampleTest {

  @Autowired
  SampleDao dao;

  @Test
  void test_getOne() {
    Sample s = dao.findById(1);
    assertEquals(s.getId(), 1);
  }
}

MockMvc

MockMvc とは

MockMvc は、Controller のテストとして、対象のパスにリクエストを送信するために使用します。 MockMvc を使用する場合は、以下のように@AutoConfigureMockMvcを付与します。

@SpringBootTest
@AutoConfigureMockMvc
public class SampleTest {

  @Autowired
  MockMvc mockMvc;

  @Test
  void test() {
    mockMvc.perform(get("/api/v1/sample"))
           .andExpect(status().isOk());
  }
}

上記の例では、/api/v1/sampleに GET メソッドでリクエストを送信し、HTTP ステータスとして 200 が返ってくることをテストしています。

リクエストの情報は、perform()に設定します。 リクエストメソッドに応じたメソッド(get()など)でリクエスト先を設定します。

リクエストの結果は、andExpect()にてテストできます。 今回は HTTP ステータスが 200 であることを検証するため、status().isOK()としています。

レスポンスボディの取得

API の結果として、レスポンスボディの情報を取得するには以下のようにします。

  @Test
  void test() {
    String result = mockMvc.perform(get("/api/v1/sample"))
                          .andReturn()
                          .getResponse()
                          .getContentAsString();
  }

andReturn()によってリクエストやレスポンスなどの情報を取得することができます。 今回はレスポンスの情報が欲しいため、getResponse()としています。

あとは、レスポンスボディの情報を JSON 文字列として取得するためにgetContentAsString()としています。

JSON の送信

JSON を送信する場合は、以下のように設定します。

@Test
void test() {
  //JSONを生成
  Sample s = new Sample(1, "Tanaka", "Taro");
  ObjectMapper mapper = new ObjectMapper();
  String json = mapper.writeValueAsString(s);

  //リクエストを送信
  mockMvc.perform(post("/api/v1/sample")
           .contentType(MediaType.APPLICATION_JSON)
           .content(json));
}

JSON を送信するため、contentType()Content-Type: application/jsonとなるように設定します。 リクエストボディに JSON を設定するには、content()を使用します。

リクエストヘッダーの設定

リクエストヘッダーを設定するには、header()を使用します。 以下は、Authorizationに認証トークンを設定する例です。

@Test
void test() {
  mockMvc.perform(post("/api/v1/sample")
           .header("Authorization", "Bearer " + token));
}

動的テストの生成

ここでは、複数パターンの JSON を送信するテストを行うことを考えます。 例として以下の POST に対して複数回リクエストを送信します。

SampleParam.java
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SampleParam {

  @NotBlank
  private String id;

  @NotBlank
  @Length(max = 32)
  private String firstName;

  @NotBlank
  @Length(max = 32)
  private String lastName;
}
SampleController.java
@RestController
@RequestMapping("/api/v1/sample")
public class SampleController {

  @Autowired
  private SampleService service;

  @PostMapping
  public void create(@RequestBody @Validated SampleParam param) {
    service.create(param);
  }
}

JSON の作成

まずは基本となる JSON(オブジェクト)を生成します。

SampleParam param = new SampleParam("0001", "Taro", "Tanaka");

パラメータ―用のクラス(SampleParam)に@Builderを付与していることから、 一部の情報を変更した JSON を作成できます。 これをListで生成しておきます。

List<SampleParam> params = new ArrayList<>();
params.add(param);
params.add(param.builder().id("0002").build());
params.add(param.builder().id("0003").build());
params.add(param.builder().id("0004").build());

@TestFactory

@TestFactoryによって、上記で作成した JSON を順に送信するテストを動的に生成します。 Stream API を使用することで、以下のように作成することができます。

@TestFactory
Iterator<DynamicTest> test() {
  ObjectMapper mapper = new ObjectMapper();
  return params.stream().map(e -> dynamicTest("test", () -> {
    String json = mapper.writeValueAsString(e);
    mockMvc.perform(post("/api/v1/sample")
              .contentType(MediaType.APPLICATION_JSON)
              .content(json))
           .andExpect(status().isOk());
  })).iterator();
}