かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Gradle で Multi-project を作成する ( その10 )( doma2lib+cmdapp+webapp編、sample-cmdapp プロジェクトを作成する2 )

概要

記事一覧はこちらです。

Gradle で Multi-project を作成する ( その9 )( doma2lib+cmdapp+webapp編、sample-cmdapp プロジェクトを作成する ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Doma 2 の Entity、Dao を提供するライブラリ+Spring Boot ベースのコマンドラインアプリケーション+Spring Boot ベースの Web アプリケーションの Multi-project を作成します。
    • sample-cmdapp プロジェクトを作成します。前回からの続きで、今回はテストの作成、及びコマンドラインから実行した動作確認を行います。

参照したサイト・書籍

  1. Shortest way to get File object from resource in Groovy
    https://stackoverflow.com/questions/39245934/shortest-way-to-get-file-object-from-resource-in-groovy

  2. Spring start a transaction with object created by new
    https://stackoverflow.com/questions/4707193/spring-start-a-transaction-with-object-created-by-new

    • applicationContext.getAutowireCapableBeanFactory().applyBeanPostProcessorsAfterInitialization(...) で手動で Bean を登録する方法を参考にしました。

目次

  1. テストを作成する
  2. コマンドラインから実行して動作確認する
  3. 補足
    1. sample-cmdapp でも Flyway は動作している

手順

テストを作成する

最初にテストで利用する CSV ファイルを作成します。sample-cmdapp/src/test/resources/employee.csv を新規作成し、以下の内容を記述します。

"name","age","sex"
"高橋 蓮","15","男"
"渡辺 結月","24","女"

次に sample-cmdapp/src/main/java/ksbysample/app/samplecmdapp/EmployeeDataCsvToDbLoader.java のテストクラスを作成します。

@SpringBootTest アノテーションが付与されたクラスのテストメソッドを実行するとテストメソッド内の処理が実行される前に CommandLineRunner インターフェースを実装したクラスの run メソッドが実行されてしまうのですが、以下の方法で run メソッドが自動で実行されないようにします。

  • EmployeeDataCsvToDbLoader クラスに @ConditionalOnProperty(value = { "batch.execute" }, havingValue = "EmployeeDataCsvToDbLoader") アノテーションを付与して、batch.execute=EmployeeDataCsvToDbLoader が設定されない限り自動で Bean に登録されないようにします。
  • EmployeeDataCsvToDbLoader クラスのコンストラクタに渡すオブジェクト(Bean)は、テストクラスのフィールドに @Autowired アノテーションを付与して定義しておきます。
  • テストメソッドの最初で EmployeeDataCsvToDbLoader クラスのインスタンスを生成してから context.getAutowireCapableBeanFactory().applyBeanPostProcessorsAfterInitialization(...) を呼び出して手動で Bean に登録します。手動で登録すると CommandLineRunner#run メソッドは自動で実行されません。
f:id:ksby:20190501011141p:plainf:id:ksby:20190501011213p:plain

sample-cmdapp/src/test/groovy/ksbysample/app/samplecmdapp/EmployeeDataCsvToDbLoaderTest.groovy が新規作成されますので、以下の内容を記述します。

package ksbysample.app.samplecmdapp

import groovy.sql.Sql
import ksbysample.lib.doma2lib.dao.EmployeeDao
import org.modelmapper.ModelMapper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.context.ApplicationContext
import spock.lang.Specification

import javax.sql.DataSource

// 通常は spring.profiles.active は IntelliJ IDEA の JUnit の Run/Debug Configuration と build.gradle に定義するが、
// 今回はテストが1つしかないので @SpringBootTest の properties 属性で指定する
@SpringBootTest(properties = ["spring.profiles.active=develop"])
class EmployeeDataCsvToDbLoaderTest extends Specification {

    @Autowired
    private ApplicationContext context

    @Autowired
    private DataSource dataSource

    @Autowired
    private final EmployeeDao employeeDao

    @Autowired
    private final ModelMapper modelMapper

    def sql

    void setup() {
        sql = new Sql(dataSource)
    }

    void cleanup() {
        sql.close()
    }

    def "EmployeeDataCsvToDbLoader.run メソッドを実行すると employee.csv のデータが employee テーブルに登録される"() {
        setup:
        // EmployeeDataCsvToDbLoader クラスは batch.execute=EmployeeDataCsvToDbLoader が指定されていないと Bean として
        // 登録されず run メソッドが自動で実行されない。テストでは手動で Bean に登録することで run メソッドが自動実行されることを
        // 回避する。
        EmployeeDataCsvToDbLoader employeeDataCsvToDbLoader =
                new EmployeeDataCsvToDbLoader(employeeDao, modelMapper)
        employeeDataCsvToDbLoader = (EmployeeDataCsvToDbLoader) context
                .getAutowireCapableBeanFactory()
                .applyBeanPostProcessorsAfterInitialization(employeeDataCsvToDbLoader, "employeeDataCsvToDbLoader")

        // src/test/resources の下の employee.csv の File オブジェクトを取得する
        def url = getClass().getResource("/employee.csv")
        def employeeCsvFile = new File(url.toURI())

        // employee テーブルからテストデータを削除する
        sql.execute("delete from employee where name in ('高橋 蓮', '渡辺 結月')")

        expect:
        employeeDataCsvToDbLoader.run("-csvfile=${employeeCsvFile.absolutePath}")
        def results = sql.rows("select name, age, sex from employee where name in ('高橋 蓮', '渡辺 結月')")
        results == [
                [name: "高橋 蓮", age: 15, sex: "男"],
                [name: "渡辺 結月", age: 24, sex: "女"]
        ]

        cleanup:
        sql.execute("delete from employee where name in ('高橋 蓮', '渡辺 結月')")
    }

}

テストを実行して成功することを確認します。

f:id:ksby:20190501013930p:plain

コマンドラインから実行して動作確認する

employee テーブルにテストデータが登録されていないことを確認した後、

f:id:ksby:20190501014632p:plain

sample-cmdapp-1.0.0-RELEASE.jar が生成されている D:\project-springboot\ksbysample-boot-miscellaneous\gradle-multiprj-doma2lib-cmdwebapp\sample-cmdapp\build\libs に移動してから java -Dspring.profiles.active=develop -Dbatch.execute=EmployeeDataCsvToDbLoader -jar sample-cmdapp-1.0.0-RELEASE.jar -csvfile=D:\project-springboot\ksbysample-boot-miscellaneous\gradle-multiprj-doma2lib-cmdwebapp\sample-cmdapp\src\test\resources\employee.csv コマンドを実行します。

f:id:ksby:20190501015315p:plain f:id:ksby:20190501015409p:plain

employee テーブルを確認するとテストデータが登録されています。

f:id:ksby:20190501015447p:plain

問題なさそうです。

最後に sample-cmdapp プロジェクトのディレクトリ構成を記載します。

f:id:ksby:20190501015848p:plain

sample-cmdapp-1.0.0-RELEASE.jar の中身を見てみると以下のようになっており doma2-lib-1.0.0-RELEASE.jar が lib ディレクトリの下に入っています。

f:id:ksby:20190501053130p:plain

補足

sample-cmdapp でも Flyway は動作している

現在の設定では sample-cmdapp を実行した時も Flyway は動作しています。確認してみます。

docker-compose down コマンドを実行後、docker/mysql/data の下をクリアします。

docker-compose.yml の flyway の設定をコメントアウトした後、

version: '3'

services:
  ..........

#  flyway:
#    image: boxfuse/flyway:${FLYWAY_VERSION}-alpine
#    container_name: flyway
#    environment:
#      - TZ=Asia/Tokyo
#    volumes:
#      - ./doma2-lib/src/main/resources/db/migration:/flyway/sql
#    command: -url=${FLYWAY_URL} -user=${FLYWAY_USER} -password=${FLYWAY_PASSWORD} -connectRetries=60 migrate
#    depends_on:
      - mysql
    # 下の3行は debug 用
    # うまく動かない時はコメントアウトを解除した後、
    # docker exec -it flyway /bin/sh
    # で接続してから
    # flyway <command に記述した文字列>
    # を実行してみる
    #
    # entrypoint: /bin/sh
    # stdin_open: true
    # tty: true

docker-compose up -d コマンドを実行します。

adminer にログインして sampledb を見るとテーブルは何もありませんが、

f:id:ksby:20190501021157p:plain

コマンドラインから java -Dspring.profiles.active=develop -Dbatch.execute=EmployeeDataCsvToDbLoader -jar sample-cmdapp-1.0.0-RELEASE.jar -csvfile=D:\project-springboot\ksbysample-boot-miscellaneous\gradle-multiprj-doma2lib-cmdwebapp\sample-cmdapp\src\test\resources\employee.csv を実行してから、

f:id:ksby:20190501021340p:plain f:id:ksby:20190501021435p:plain

sampledb を確認すると employee と flyway_schema_history の2つのテーブルが作成されており、

f:id:ksby:20190501021538p:plain

employee テーブルにも doma2-lib/src/main/resources/db/migration/V1__create_table.sql の2件と sample-cmdapp/src/test/resources/employee.csv の2件の合計4件のデータが登録されています。

f:id:ksby:20190501021718p:plain

履歴

2019/05/01
初版発行。