21
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Spring Boot + JUnit + h2でスタンドアローンな機能テストをやる

Posted at

Spring Boot + MySQLでシンプルなWeb REST APIサーバを実装する - Qiita

Outline

Spring bootで作成したREST APIの機能テストをやる。
httpリクエストを送信し、レスポンスと、DBの状態をテストする。

インメモリDB(H2)を利用することで、DBサーバが無くても実行可能なテストを組む。

H2

H2 Database Engine

準備

dependency

プロジェクトの依存にH2を追加する。

build.gradle
testCompile("com.h2database:h2:${h2Version}")

接続設定

src/test/resources/application.yml
ここに置くことで、テスト時に読み込まれるprofileを定義できる。
テスト時はMySQLではなく、H2の設定を書く。

application.yml
spring:
  datasource:
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:;DB_CLOSE_ON_EXIT=TRUE;MODE=MySQL
    username: sa
    password:

  jpa:
    hibernate:
      ddl-auto: none

DDL

src/test/resources/schema.sql
Spring Bootアプリケーションでは、schema.sqlというファイル名のスクリプトは起動時に実行される。
DDLを書いておく。

CREATE TABLE IF NOT EXISTS test_users (
  id VARCHAR(18) NOT NULL
  , value VARCHAR(255) DEFAULT NULL
  , created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
  , updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  , PRIMARY KEY(id)
);

DML

src/test/resources/data.sql
schema.sql同様、data.sqlというファイルも起動時に実行される。
テストに利用するデータを起動時に挿入しておく。

data.sql
INSERT INTO test_users ( id, value ) VALUES ( 'test_id', 'test_value' );

UserApiTests.java

ユーザ登録のテストのみ抜粋

UserApiTests.java


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserApiTests {
    private final static String TABLE = "test_users";
    private static final String SELECT_SQL = String.format("SELECT * FROM %s WHERE ID = ?", TABLE);

    private static final String BASE_PATH = "/v1/users/";

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    public void postUser() throws URISyntaxException {
        String body = "{\"id\":\"test_post_id\",\"value\":\"test_post_value\"}";
        String exceptedResp = body;

        RequestEntity req = RequestEntity
                .post(new URI(BASE_PATH))
                .header("Content-Type", MediaType.APPLICATION_JSON_VALUE)
                .body(body);
        ResponseEntity actualResp = this.testRestTemplate.exchange(req, String.class);

        assertThat(actualResp.getBody().toString()).isEqualTo(exceptedResp);
        assertThat(actualResp.getStatusCode()).isEqualTo(HttpStatus.CREATED);

        Map<String, Object> actualData = this.jdbcTemplate.queryForMap(SELECT_SQL, "test_post_id");
        assertThat(actualData.get("id")).isEqualTo("test_post_id");
        assertThat(actualData.get("value")).isEqualTo("test_post_value");
    }


SpringBootTest

@SpringBootTestを付与することで、Springアプリケーションが起動する。
これにより、DIコンテナなどSpringの機能が利用可能となる。
そのぶんテスト実行に時間がかかるので単体テストとかでペタペタ貼らないほうがいい気がする。

Http通信部分

@SpringBootTestの引数を以下のように設定することで、空いているポートでWebサーバが起動する。

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

このポートにアクセスする方法はいくつかあるが、今回はTestRestTemplateを使う
インタフェースなどRestTemplateとほぼ変わらない。
指定するURIにホスト名などを含めず、ベースパス以降にするだけで、テスト用に立ちたがっているアプリケーションと通信する。
Spring Boot Reference Guide
インスタンスはDIコンテナ経由で取得可能。

@Autowired
private TestRestTemplate testRestTemplate;

DB部分

JdbcTemplateを利用して、DBの状態を取得する。
これもDIコンテナ経由でインスタンスが取得可能。

queryForMapというインタフェースでMap形式でレコードを参照可能。

Map<String, Object> actualData = this.jdbcTemplate.queryForMap(SELECT_SQL, "test_post_id");
assertThat(actualData.get("id")).isEqualTo("test_post_id");
assertThat(actualData.get("value")).isEqualTo("test_post_value");

ちなみに0件をnullとかでチェックすることはできないようなので、そういうときはListを使ってる。

List<Map<String, Object>> actualDataList = this.jdbcTemplate.queryForList(SELECT_SQL, "test_empty_id");
assertThat(actualDataList.size()).isEqualTo(0);
21
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?