LoginSignup
11
9

More than 5 years have passed since last update.

Spring TestでEmbedded MySQLを使う方法

Posted at

ちょっと前に竹添さん(@takezoen)がブログで紹介していた、Embedded MySQLJUnitで使う方法です。

簡単にできたけど、今後同じように迷わないように備忘録として残します。

各バージョン

訳あってSpringのバージョンが3.2.8.RELEASEですが、4系の最新版でも問題ないです。

やり方1(JUnit@ClassRuleを使う方法)

EmbeddedMySQL.java
package jp.ijfumi.test.db;

import com.wix.mysql.EmbeddedMysql;
import com.wix.mysql.config.MysqldConfig;
import org.junit.rules.ExternalResource;

import static com.wix.mysql.EmbeddedMysql.anEmbeddedMysql;
import static com.wix.mysql.config.MysqldConfig.aMysqldConfig;
import static com.wix.mysql.distribution.Version.v5_6_21;

public class EmbeddedMySQL extends ExternalResource {
    private EmbeddedMysql mysqld;

    protected void before() {
        if (mysqld == null) {
            MysqldConfig config = aMysqldConfig(v5_6_21)
                    .withPort(3306)
                    .withUser("root", "password")
                    .build();

            mysqld = anEmbeddedMysql(config)
                    .addSchema("test")
                    .start();
        }
    }

    protected void after() {
        mysqld.stop();
        mysqld = null;
    }
}

を作成し、テストクラスにて@ClassRuleを指定するだけです。

SampleTest.java
package jp.ijufumi.sample.test;

import jp.ijfumi.test.db. EmbeddedMySQL;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.ExternalResource;

public class SampleTest {
  @ClassRule
  public static ExternalResource resource = new EmbeddedMySQL();
}

ただ、これだとMySQLを使わないテストケースだけ実行する場合でも、MySQLを起動してしまいます。

やり方2(TestExecutionListenerを使う方法)

EmbeddedMySQLConfig.java
package jp.ijufumi.sample.test.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Inherited
@Documented
/**
 * テスト実行時に組み込みMySQLを使用する時に設定情報を指定するアノテーション。
 */
public @interface EmbeddedMySQLConfig {
    /** ポート番号 */
    int port() default 3306;

    /** 接続ユーザ */
    String user() default "root";
    /** 接続ユーザパスワード */
    String password() default "password";
}

と、

EmbeddedMySQLTestExecutionListener.java
package jp.ijufumi.sample.test.support;

import jp.ijufumi.sample.test.annotation.EmbeddedMySQLConfig;

import com.wix.mysql.EmbeddedMysql;
import com.wix.mysql.config.MysqldConfig;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;

import static com.wix.mysql.EmbeddedMysql.anEmbeddedMysql;
import static com.wix.mysql.config.MysqldConfig.aMysqldConfig;
import static com.wix.mysql.distribution.Version.v5_6_21;

/**
 * EmbeddedMySQLを起動させるExecutionListenerクラス。
 * 使う場合は、対象のクラスやメソッドに@EmbeddedMySQLConfigアノテーションを指定する。
 */
public class EmbeddedMySQLTestExecutionListener extends AbstractTestExecutionListener {
    private EmbeddedMysql mysqld;
    private ExecuteType type;

    public void beforeTestClass(TestContext testContext) throws Exception {
        EmbeddedMySQLConfig config = testContext.getTestClass().getAnnotation(EmbeddedMySQLConfig.class);
        if (config != null) {
            start(config.port(), config.user(), config.password());
            type = ExecuteType.CLASS;
        }
    }

    public void beforeTestMethod(TestContext testContext) throws Exception {
        EmbeddedMySQLConfig config = testContext.getTestMethod().getAnnotation(EmbeddedMySQLConfig.class);
        if (config == null) {
            return;
        }
        if (mysqld == null)
        {
            start(config.port(), config.user(), config.password());
            type = ExecuteType.METHOD;
        }
    }

    public void afterTestMethod(TestContext testContext) throws Exception {
        if (type != null && ExecuteType.METHOD.equals(type)) {
            stop();
        }
    }

    public void afterTestClass(TestContext testContext) throws Exception {
        stop();
    }

    private void start(int port, String user, String password) {
        if (mysqld == null) {
            MysqldConfig config = aMysqldConfig(v5_6_21)
                    .withPort(port)
                    .withUser("root", "")
                    .withUser(user, password)
                    .build();

            mysqld = anEmbeddedMysql(config)
                    .addSchema("local_jp_cotoco")
                    .start();
        }
    }

    private void stop() {
        if (mysqld != null) {
            mysqld.stop();
            mysqld = null;
        }
    }

    enum ExecuteType {
        CLASS,
        METHOD;
    }
}

を作成し、テスト対象に指定するだけです。

SampleTest.java
package jp.ijufumi.sample.test;

import jp.ijufumi.sample.test.annotation.EmbeddedMySQLConfig;
import jp.ijufumi.sample.test.support.EmbeddedMySQLTestExecutionListener;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;

import org.junit.runner.RunWith;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:META-INF/spring/applicationContext-test.xml"})
@TestExecutionListeners({
        EmbeddedMySQLTestExecutionListener.class
})
@EmbeddedMySQLConfig
public class SampleTest {
}

おわりに

個人的には、やり方2の方が好みです。

11
9
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
11
9