In the next chapter of testing with regards to dependencies, I am putting tests around a DAO object. The way I was approaching the tests for this DAO was to setup a transaction in the setup method, insert some data to test against, run the test, and then rollback any changes in the teardown method. The problem I have run into with this DAO is that the database table it is working with has a couple of foreign keys set on it. Thus, I cannot just insert a simple set of data into this table - I have to have matching records in all of the linked tables etc. and therefore, defining a data set to work with is not a small undertaking. I can’t see a way to remove the dependency of the database though since part of the test I would think would be to make sure the SQL query code is written correctly.
So, how do people approach DAO testing in a real world environment where tables are linked and not just standalone? Do you create a large data set, populating multiple tables just to run one test? Or, is there another way to approach this?
Thanks
-- Jeff
Thanks Brian. I just wanted to make sure I was not missing a obvious answer somewhere else.
-- Jeff
I myself struggle with this a lot, and usually I end up writing tests
that do waaaay too much. I guess I just err on the side of "too much
is better than nothing", although the result is almost always more
brittle tests and hard-to-maintain tests.
I wish I could find the time or inclination to do it properly, and I
think "properly" probably means a) separate databases and b) scripts
for maintaining the data model between databases. the problem there is
just the time it takes to keep the "unit test" database and the other
databases in sync. Is it worth it? I have no doubt. But I'm lazy I
guess, and particularly when you're working alone on this stuff and
noone else on the team, including managers, supports it, it becomes a
larger challenge.
here, for me, is one of those cases where building less-coupled
objects is a noble goal, but I'm not there yet. the book JUnit Recipes
has some good examples of this. For example, they use a generic
QueryExecutor object, and it's got a "delete", for example. and that
delete takes in a PreparedStatement and a list of parameters. And they
test that delete one time.... because if the delete works on one
prepared statement, it'll work on all of them. But what they do next
is they factor out the parameter creation into a separate object, and
then that's what they test. i.e. "pass in these args to some
QueryBuilder function, and did it return the appropriate parameters to
pass to the QueryExecutor.
So, I can see how this makes it easier to test. But damn...
The other thing the book advocates is a method for testing the sql
string itself rather than always hitting the database to verify that
the sql is OK. Not sure how I feel about that since when I look at
the kind of queries I write at work.... yikes.
Jeff, I guess this is my long-winded answer that simply says "we're
all in this boat, brother".
i do look forward to hearing more/better/alternate solutions to these
kinds of problems.
Best Wishes,
Peter
Although Transfer is a pain in the ass to test around - with its
"strict" typing you end up having to create a lot of mocks all
injected into each other in order to mock any persistence operations
or to mock the base class for a decorator. Also, since it generates
methods dynamically at runtime, the mock frameworks don't work with
Transfer Objects (because they mock based on metadata - and most of
the methods don't exist in the metadata!).
I'm still trying to figure out a good way to unit test data gateways
based on Transfer and/or beans based on TransferDecorator.
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood