Skip to content

Commit

Permalink
Add tests for DbMigrateCommand
Browse files Browse the repository at this point in the history
Check 4 use cases:

* Migration of pending migrations to the DB.
* Dry-run mode (printing the pending change set to the console).
* Migration of limited amount of changes.
* Help page (description of the command and available arguments)
  • Loading branch information
arteam committed May 26, 2015
1 parent 539eb23 commit ab858b7
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 3 deletions.
7 changes: 7 additions & 0 deletions dropwizard-migrations/pom.xml
Expand Up @@ -43,5 +43,12 @@
<version>${h2.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-jdbi</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -1,7 +1,9 @@
package io.dropwizard.migrations;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import io.dropwizard.Configuration;
import io.dropwizard.db.DatabaseConfiguration;
import liquibase.Liquibase;
Expand All @@ -10,9 +12,18 @@
import net.sourceforge.argparse4j.inf.Subparser;

import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.util.List;

public class DbMigrateCommand<T extends Configuration> extends AbstractLiquibaseCommand<T> {

private PrintStream outputStream = System.out;

@VisibleForTesting
void setOutputStream(PrintStream outputStream) {
this.outputStream = outputStream;
}

public DbMigrateCommand(DatabaseConfiguration<T> strategy, Class<T> configurationClass) {
super("migrate", "Apply all pending change sets.", strategy, configurationClass);
}
Expand Down Expand Up @@ -43,16 +54,16 @@ public void configure(Subparser subparser) {
public void run(Namespace namespace, Liquibase liquibase) throws Exception {
final String context = getContext(namespace);
final Integer count = namespace.getInt("count");
final Boolean dryRun = namespace.getBoolean("dry-run");
final boolean dryRun = MoreObjects.firstNonNull(namespace.getBoolean("dry-run"), false);
if (count != null) {
if (dryRun) {
liquibase.update(count, context, new OutputStreamWriter(System.out, Charsets.UTF_8));
liquibase.update(count, context, new OutputStreamWriter(outputStream, Charsets.UTF_8));
} else {
liquibase.update(count, context);
}
} else {
if (dryRun) {
liquibase.update(context, new OutputStreamWriter(System.out, Charsets.UTF_8));
liquibase.update(context, new OutputStreamWriter(outputStream, Charsets.UTF_8));
} else {
liquibase.update(context);
}
Expand Down
@@ -0,0 +1,116 @@
package io.dropwizard.migrations;

import com.google.common.collect.ImmutableMap;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.db.DatabaseConfiguration;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
import org.junit.Before;
import org.junit.Test;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.Handle;

import java.io.*;
import java.util.List;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

public class DbMigrateCommandTest {

private DbMigrateCommand<TestMigrateConfiguration> migrateCommand = new DbMigrateCommand<>(
new DatabaseConfiguration<TestMigrateConfiguration>() {
@Override
public DataSourceFactory getDataSourceFactory(TestMigrateConfiguration configuration) {
return configuration.getDataSource();
}
}, TestMigrateConfiguration.class);
private TestMigrateConfiguration conf;
private String databaseUrl;

private static String createTempFile() {
try {
return File.createTempFile("test-example", null).getAbsolutePath();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}

@Before
public void setUp() throws Exception {
databaseUrl = "jdbc:h2:" + createTempFile();

final DataSourceFactory dataSource = new DataSourceFactory();
dataSource.setDriverClass("org.h2.Driver");
dataSource.setUser("sa");
dataSource.setUrl(databaseUrl);
conf = new TestMigrateConfiguration(dataSource);
}

@Test
public void testRun() throws Exception {
migrateCommand.run(null, new Namespace(ImmutableMap.<String, Object>of()), conf);
try (Handle handle = new DBI(databaseUrl, "sa", "").open()) {
final List<Map<String, Object>> rows = handle.select("select * from persons");
assertThat(rows).hasSize(1);
assertThat(rows.get(0)).isEqualTo(
ImmutableMap.of("id", 1, "name", "Bill Smith", "email", "bill@smith.me"));
}
}

@Test
public void testRunFirstTwoMigration() throws Exception {
migrateCommand.run(null, new Namespace(ImmutableMap.of("count", (Object) 2)), conf);
try (Handle handle = new DBI(databaseUrl, "sa", "").open()) {
assertThat(handle.select("select * from persons")).isEmpty();
}
}

@Test
public void testDryRun() throws Exception {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
migrateCommand.setOutputStream(new PrintStream(baos));
migrateCommand.run(null, new Namespace(ImmutableMap.of("dry-run", (Object) true)), conf);
assertThat(baos.toString("UTF-8")).startsWith(String.format(
"-- *********************************************************************%n" +
"-- Update Database Script%n" +
"-- *********************************************************************%n"));
}

@Test
public void testPrintHelp() throws Exception {
final Subparser subparser = ArgumentParsers.newArgumentParser("db")
.addSubparsers()
.addParser(migrateCommand.getName())
.description(migrateCommand.getDescription());
migrateCommand.configure(subparser);

final ByteArrayOutputStream baos = new ByteArrayOutputStream();
subparser.printHelp(new PrintWriter(baos, true));

assertThat(baos.toString("UTF-8")).isEqualTo(String.format(
"usage: db migrate [-h] [--migrations MIGRATIONS-FILE] [--catalog CATALOG]%n" +
" [--schema SCHEMA] [-n] [-c COUNT] [-i CONTEXTS] [file]%n" +
"%n" +
"Apply all pending change sets.%n" +
"%n" +
"positional arguments:%n" +
" file application configuration file%n" +
"%n" +
"optional arguments:%n" +
" -h, --help show this help message and exit%n" +
" --migrations MIGRATIONS-FILE%n" +
" the file containing the Liquibase migrations for%n" +
" the application%n" +
" --catalog CATALOG Specify the database catalog (use database%n" +
" default if omitted)%n" +
" --schema SCHEMA Specify the database schema (use database default%n" +
" if omitted)%n" +
" -n, --dry-run output the DDL to stdout, don't run it%n" +
" -c COUNT, --count COUNT%n" +
" only apply the next N change sets%n" +
" -i CONTEXTS, --include CONTEXTS%n" +
" include change sets from the given context%n"));
}
}
@@ -0,0 +1,17 @@
package io.dropwizard.migrations;

import io.dropwizard.Configuration;
import io.dropwizard.db.DataSourceFactory;

public class TestMigrateConfiguration extends Configuration {

private DataSourceFactory dataSource;

public TestMigrateConfiguration(DataSourceFactory dataSource) {
this.dataSource = dataSource;
}

public DataSourceFactory getDataSource() {
return dataSource;
}
}
31 changes: 31 additions & 0 deletions dropwizard-migrations/src/test/resources/migrations.xml
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">

<changeSet id="1" author="db_dev">
<createTable tableName="persons">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(256)">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>

<changeSet id="2" author="db_dev">
<addColumn tableName="persons">
<column name="email" type="varchar(128)"/>
</addColumn>
</changeSet>

<changeSet id="3" author="db_dev">
<insert tableName="persons">
<column name="name" value="Bill Smith"/>
<column name="email" value="bill@smith.me"/>
</insert>
</changeSet>
</databaseChangeLog>

0 comments on commit ab858b7

Please sign in to comment.