public class SimpleTest extends SpringIntegrationTestCase {
@LoadDb(datafile = "tests-data/empty.xml")
@CheckDb(datafile = "tests-data/singleentry.xml")
public void testSimple() throws Exception {
System.out.println("Testing");
Connection conn = DatabaseApplicationDetails.getInstance().getDb
UnitConnection(null)
.getConnection();
conn.createStatement().execute("insert into customer values()");
}
(...)
}
This test does not actually use any Spring beans. Instead, it borrows a connection from Testaco in order to manually insert something in the database to illustrate how Testaco will check the new contents of the database.
When this test runs, the @LoadDb annotation will cause the database to be loaded with the contents of the referenced xml file. The path is relative to the root of your project.
If any extra setup or teardown is needed for your tests, the onOnSetUp and onOnTearDown methods will be called by the base classes, and can be overridden by your test.
The next phase of a test is the actual contents of a single test, which will be run as any other test. If the test completes without error, the CheckDb annotation will cause the contents of the database to be checked.
If your application uses more than one database, please feel free to add more LoadDb and CheckDb annotations as necessary to load and control these other databases.
import junit.framework.TestSuite;
public class ApplicationTestSuite extends DatabaseTestSuite {
@Override
public String getDatabaseSchemaDefinition(String databaseKey) throws Exception {
return "DROP TABLE IF EXISTS customer;\n" +
"CREATE TABLE `customer` (\n"+
"`id` int(11) NOT NULL auto_increment,\n"+
"`name` varchar(20) default NULL,\n"+
"PRIMARY KEY (`id`)\n"+
") ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;\n"+
"";
}
public static TestSuite suite() {
TestSuite temp = new TestSuite();
//Test setup goes first
temp.addTestSuite( ApplicationTestSuite.class );
//Then add any other tests
return temp;
}
}
This is an example of the support for database refactoring support in Testaco. The getDatabaseSchemaDefinition method should return your DDL code (the SQL statements that define your database) for your different databases. In the example, there is only one database, so there is no check on the databaseKey. The databaseKey is the same key used when defining the the database details in the testaco configuration file.
In the example, the DDL is hard coded. This is strongly discouraged. Your DDL should be stored in a revision control system in such a way that it is easy for you to get hold of a specific version of the DDL that works with a specific version of your code. If you have several applications using your databases, there should be a separate deliverable used by all your applications that is treated as any other piece of code.
I would suggest that your DDL gets released and branched, just as you would do with any of your other code. This way, there will be no extra overhead with finding out how versioning should work.
When you run this test suite, the first thing that will happen is that a special kind of test will run. This test will rebuild your databases from scratch and then check them against the "empty" DbUnit file defined in the Testaco application configuration file. If there is a mismatch, you will be told about this. If you are running within Eclipse, the Testaco Eclipse plugin will pick up this error, show you what the differences are, and then let you migrate your tests to the new schema. Your tests should then hopefully run so you can start adding functionality to your new features.
There are some misfeatures in DbUnit that it is necessary to work around.
DbUnit cannot handle the MySql "unsigned" keyword. Feel free to use the unsigned keyword in your production DDL, but please remove it from the version you use for testing.
DbUnit does not handle foreign keys gracefully. This leads to errors when trying to load data sets since the nodes referred to by a foreign key may be inserted before the parent nodes, causing errors. There are two workarounds. One is removing foreign keys in your test DDL. This is a poor choice since there may be issues that slip through, and which will appear in production. The other way of solving the issue was proposed by Matt Raible. He suggests adding "sessionVariables=FOREIGN_KEY_CHECKS=0" to the JDBC URL used by the testaco library. This is a non-intrusive change that only affects operations done by testaco, and I strongly suggest using this approach.