views:

137

answers:

2

Hi,

I've gotton to the point in my simple project where I'm ready to unit test the DAL.

I basically have a class called FooDataAccess with several very simple functions, lets say 3 of them like this:

int InsertFoo(string fooName)
void UpdateFoo(int fooID, string fooName)
void InsertFoosDepedency(int fooID, string someValue)

What I did was this - put 4 SQL Scripts inside my unit test project, the last one as am embedded resource.

1) Create (Unit test) Database Script, 2) Create Objects Script, 3) Insert Lookup Table Values and 4) Delete All But Lookup Table Values

The idea is, anyone first using the project should manually run scripts 1-3 by hand as a one-time setup. Then execute script #4 on start-up of each unit test... (in small apps, you could even run all of them at the testing level)

OK, so far so good...

So I have my unit test database setup, as an empty slate. Testing the first function InsertFoo() is obviously very simple. I call the function, then just Assert(ExecuteSQL("select count(*) from foo") > 1), Assert(ExecuteSQL("select fooName from t_foo") = expected)), etc..

Where I'm a bit stuck is the ones which require dependencies, like the 3rd function in my example, or even the update.

Would it make sense to temporarily drop all foreign key constraints for the scope of my test? Otherwise, in order to unit test the InsertFoosDepedency(int fooID, string someValue) function, I would have to execute some arbitrary sql first (manually insert a record to the FOO table and return the FooID)...

OR, should I just do the latter?

Any and all feedback is greatly appreciated.

UPDATE: Its working cleanly with inline SQL to create the dependents. I guess I'm just looking for comments & critisism on this method for unit testing DAL. Thanks again

+1  A: 

I would say never muck around with your schema for the sake of tests. If you fail to put it back or your code to put it back fails you'll find yourself in a mess very quickly.

Can you use Mock Objects?

If no, I think all you can do is set up database pre-reqs for each test.

You could consider a separate class for each test and use Setup and Teardown methods to get the database in the right condition for the tests.

Or you just have to do your test-specific setup in the Test method (and you could use Teardown to empty the DB afterwards).

serialhobbyist
I am using Mock Objects already, for all callers on my DAL.But I would still like to unit test the DAL functions themselves still.I'm not too scared of screwing up the database, because this is a database created specifically for unit-testing..Perhaps I should just call InsertFoo() to create my foo and get my ID for the dependencies? but would that break the concept of it being a 'unit' test???
dferraro
I'm not sure I followed you. Surely dependencies have to be inserted first, so that something can be dependent on them? Do you mean dependents rather than dependencies?
serialhobbyist
You're correct, my fault. I meant dependents. Thanks again
dferraro
Reading that again I sound like a right pedant - I was just trying to be clear. So, back to the question: I think your tests should reflect your expected usage, so if your users can just call InsertFoo() then you should test it. But if they always have to call the other one as well, shouldn't you make both methods private and call them from one uber-method? (If you're making them public so you can test them, you could consider making them internal and using InternalsVisibleToAttribute.)
serialhobbyist
+1  A: 

This sounds quite similar to what I do. I destroy all the data in the database at the start of each test and then build up just what that test requires in that tests set up phase. So for UpdateFoo I would have

void update_existingKey_updatesValue() {
   String expected = "jeff";

   clearDatabase();
   // Note I would use dbUnit.
   executeSQL("insert into foo values (1, 'fred')");

   DAL subject = new DAL(...);
   subject.update(1, expected);  

   //Note I would use dbUnit.   
   String actual = executeSQL("select name from foo where id = 1"); 
   assert(expected, actual);
}

In Java I use a tool called dbUnit, your method names suggest C# so I'll point you at dbUnit.Net however I have never used this. This provides a nicer (IMO anyway) method of populating the database and verifying the content of the database.

mlk