Following up on DbAssert I’ve made a few changes to it. They are really minor ones.

Ability to add additional conditions like this:

dbAssert.condition("id", 1).addCondition("name", "John Doe");

Another change which brings more real functionality is:

// checks if count of the records returned equals given value
dbAssert.assert_count(0);

So we’ve all here been using DbAssert for two months already and I think we’re pretty satisfied with it. But… we’ve been missing one thing – putting a datasource to a known state before executing our tests.

Everybody knows that good unit test is the test that can live on its own without any dependencies or much dependencies from other components or external datasources. Partially this can be done by mocking up external resources, but often you do really want to test your logic that retrieves something from a datasource. You want to make sure it works, don’t you? So that’s what DbAssert and DbSource are about. Yes, here is another quirky name – DbSource that allows you to put database to a known state.

Often your business logic and tests require some existing data in database, or requires your datasource being in consistent known state between test executions. It means if you test business logic that inserts customer record to database you want to be able to run it as multiple times as you want without having manually delete it after each execution. So you couldn’t end up with something like “PrimaryKeyVialationException” for the same record when you try to insert it second time. Here you go!

What DbSource does is puts your datasource in a known state plus a little bit more.

Let’s see the initialization process which is similar to DbAssert:

dbSource = DbSource.init("org/testfw/TestSources.xml", "test_source", getClass());

To clean a given table use:

dbSource.clean_table("customer");

What if I want to clean more than one table for my test?
Should I do something like this:

//wipe out all the tables available in this datasource
dbSource.clean_source();

Or something like this:

dbSource.clean_tables(new String[]{"customers", "address", "countries"})

I don’t know yet. So I’d really like to hear what you think.

Another neat feature of DbSource is fixtures. Yes, I did borrow this from RoR.
Let’s say your test relies on some data in database so you need to load this data first.

dbSource.fixture("customers");

This assumes that you want to insert records from customers.yml file to customers table.
Again, what if I want to load a number of fixtures? What is the best syntax for this?

How do we find customers.yml which is YAML file format and looks like this:

customer_one:
    id: 1
    name: John Smith
customer_two:
    id: 2
    name: Joe Doe	

To locate it we passed reference to current class in to DbSource.init() method. This implies that we have folder named fixtures on the same level as your test class which contains all your fixture files.

- MyTest.java
- fixtures/
	- customers.yml

If you don’t want to follow that convention then don’t pass class name to the DbSource init method and use full path to your fixture file.

dbSource.fixture("org/testfw/customers.yml");

There is one more thing. :) There is a way to get values from fixtures:

//load data to customers table and return fixture
final Fixture fixtures = dbSource.fixture("customers");

// get all the fields for customer_one in the fixture
final Fixture customer_one = (Fixture) fixtures.get("customer_one");

//check that value returned by business logic (customerDao) is the same that we have in database
assertEquals(customer_one.get("name"), customerDao.findById(customer_one.get("id")));

Using jUnit’s @Before and @BeforeClass annotations you can vary your cleaning strategies: before every test method so they can start on fresh instance or cleaning it once. That should give enough flexibility for your needs.

So how is it?

Advertisements