Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

ネットの検索結果でチラチラとは見ていたのですが、この度初めて自分でも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>

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away