Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
21
Help us understand the problem. What is going on with this article?

More than 5 years have passed since last update.

@tchofu

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

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

参考

21
Help us understand the problem. What is going on with this article?
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
21
Help us understand the problem. What is going on with this article?