ちょっと前に竹添さん(@takezoen)がブログで紹介していた、Embedded MySQL
をJUnit
で使う方法です。
簡単にできたけど、今後同じように迷わないように備忘録として残します。
各バージョン
訳あってSpring
のバージョンが3.2.8.RELEASE
ですが、4系の最新版でも問題ないです。
-
Java
1.8.0 update 92 -
Spring Framework
3.2.8.RELEASE -
wix-embedded-mysql
1.0.3 -
JUnit
4.12
やり方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の方が好みです。