LoginSignup
22

More than 5 years have passed since last update.

DBUnitを使うと簡潔にユニットテスト用のDBを用意できました

Posted at

ネットの検索結果でチラチラとは見ていたのですが、この度初めて自分でもDBUnitを使ってみました。ネット上のサンプルコードをほとんどそのまま実行しただけですが、私の手元でも簡単にユニットテスト用のDBとデータを準備することができました。

従来、H2 DatabaseはRunScriptで初期化用のスキーマを流し込んでいたのですが、これならJDBCドライバを選ばない気がします。

※ 他のJDBCドライバでH2 DatabaseのINIT=RunScript相当の機能が可能なのか知りません。

環境

  • DBUnit 2.5.1
  • JUnit 4.12

ユニットテストのコード(パクリですが)

以下のような感じです。Excelファイルもデータソースとして使える点は、仕事でプログラムを作る人にとってかなりのアドバンテージな気がします。

PersonRepositoryTest.java
import java.io.File;

import org.junit.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.h2.engine.Constants.UTF8;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;

import javax.sql.DataSource;

import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.excel.XlsDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;

public class PersonRepositoryTest {

    private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
    private static final String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";
    private static final String USER = "sa";
    private static final String PASSWORD = "";

    @BeforeClass
    public static void createSchema() throws Exception {
        RunScript.execute(JDBC_URL, USER, PASSWORD, "schema.sql", UTF8, false);
    }

    @Before
    public void importDataSet() throws Exception {
        IDataSet dataSet = readDataSet();
        cleanlyInsert(dataSet);
    }

    private IDataSet readDataSet() throws Exception {
//      return new FlatXmlDataSetBuilder().build(new File("dataset.xml"));
        return new XlsDataSet(new File("dataset.xls"));
    }

    private void cleanlyInsert(IDataSet dataSet) throws Exception {
        IDatabaseTester databaseTester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD);
        databaseTester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);
        databaseTester.setDataSet(dataSet);
        databaseTester.onSetup();
    }

    @Test
    public void findsAndReadsExistingPersonByFirstName() throws Exception {
        PersonRepository repository = new PersonRepository(dataSource());
        Person charlie = repository.findPersonByFirstName("Charlie");

        assertThat(charlie.getFirstName(), is("Charlie"));
        assertThat(charlie.getLastName(), is("Brown"));
        assertThat(charlie.getAge(), is(42));
    }

    @Test
    public void returnsNullWhenPersonCannotBeFoundByFirstName() throws Exception {
        PersonRepository repository = new PersonRepository(dataSource());
        Person person = repository.findPersonByFirstName("iDoNotExist");

        assertThat(person, is(nullValue()));
    }

    private DataSource dataSource() {
        JdbcDataSource dataSource = new JdbcDataSource();
        dataSource.setURL(JDBC_URL);
        dataSource.setUser(USER);
        dataSource.setPassword(PASSWORD);
        return dataSource;
    }

}
build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'provided-base'

buildscript {
    repositories {  
        maven { url 'http://jcenter.bintray.com' }
    }
    dependencies {
        classpath 'com.netflix.nebula:gradle-extra-configurations-plugin:1.12.+'
    }
}

sourceCompatibility = "$project.java_version"
targetCompatibility = "$project.java_version"

version = "$project.spec_version"
group = "$project.app_group"

repositories {
    maven { url "http://repo.maven.apache.org/maven2" }    
}

dependencies {
    provided 'org.projectlombok:lombok:1.16.+'

    compile("com.h2database:h2:1.4.+")

    // Logging
    compile('ch.qos.logback:logback-classic:1.1.+')
    compile('org.slf4j:slf4j-api:1.7.+')
    compile('org.slf4j:jcl-over-slf4j:1.7.+')
    compile('org.slf4j:log4j-over-slf4j:1.7.+')

    testCompile 'junit:junit:4.11', {
        transitive = false
    }
    testCompile 'org.hamcrest:hamcrest-all:1.3'
    testCompile 'org.dbunit:dbunit:2.5.+'
}

def defaultEncoding = 'UTF-8'
tasks.withType(JavaCompile) {
    options.encoding = defaultEncoding
}

jar {
    manifest {
        attributes 'Implementation-Title': "$project.app_description",
//                   'Main-Class': "org.gradle.Main",
                   'Implementation-Version': version + "-$project.patch_version"
    }
}

clean {
    delete 'bin', 'target', 'logs'
}

task(runMain, dependsOn: 'classes', type: JavaExec) {
    main = 'org.gradle.Main'
    classpath = sourceSets.main.runtimeClasspath
    standardInput= System.in
}

defaultTasks 'runMain'

schema.sql
create table if not exists PERSON (
    ID int identity primary key,
    NAME varchar,
    LAST_NAME varchar,
    AGE  smallint,
);
dataset.xml
<dataset>
  <PERSON NAME="Bob" LAST_NAME="Doe" AGE="18"/>
  <PERSON NAME="Alice" LAST_NAME="Foo" AGE="23"/>
  <PERSON NAME="Charlie" LAST_NAME="Brown" AGE="42"/>
</dataset>

参考

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
22