Jon
Jon

Reputation: 40062

Writing Unit Tests for method that queries database

I am learning TDD and I currently have a method that is working but I thought I'd have a go at rebuilding it using TDD.

The method essentially takes 6 parameters, queries a database, does some logic and returns a List<T>

My initial tests including checking for empty/zero defined string and int method parameter values but now I'm not sure what to do. If I wasn't using TDD, I would just create code to find the DB connection string and open up a DB connection, query the database, read the values etc.

Obviously we can't do that in Unit Testing so I was after some advice of how to proceed.

Upvotes: 12

Views: 11569

Answers (6)

herman
herman

Reputation: 12305

Another option is to start a transaction before the test and do a rollback afterwards. This way tests are independent so can still, according to some definitions, be considered unit tests.

Contrary to what's mentioned in other answers, you should refactor the code to get to a better design after the test passes. Then you can verify that your refactoring didn't break anything just by rerunning the test.

Upvotes: 2

Josh Earl
Josh Earl

Reputation: 18361

Remember that TDD is as much about good design than it is about testing. This method has too much going on; it violates the Separation of Concerns principle.

You've already identified several areas that will need to be tested:

The method essentially takes 6 parameters, queries a database, does some logic and returns a List<T>

You have several discrete steps there, and there are probably a few more hiding in the code. Breaking those up is the name of the game when it comes to TDD.

For starters, it might be a good idea to factor out the piece that performs the logic.

Is your method building a query dynamically? Break that piece out as well and test it to make sure the query is written properly.

You can put the execution of the query into a standalone repository or something similar, and write integration tests against that. That way you only have a simple test hitting the database instead of the current complex method.

If you try to test this as is, you'll likely end up with a monster test that requires a lot of setup and duplicates all of your business logic, and when it breaks it'll be unclear as to what went wrong.

Upvotes: 10

Manish Basantani
Manish Basantani

Reputation: 17509

The method essentially takes 6 parameters, queries a database, does some logic and returns a List

That seems to be too much to be a unit testable code!!

A unit testable code should be doing very specific things and doing it in small modules. So, in your case you need to refactor and break your method into following (at least):

  • data base query: wrapped inside a DataProvider with a backing interface. And your unit test would mock this interface.
  • does some logic : this is the best candidate for a unit test. This should be a module that just takes data provider interface and does the logic and returns modified list which you will validate in your unit test.

Also, remember a unit test should cover at least three scenarios for each testable module:

  • a positive test
  • a negative test
  • test throwing meaningful exception for invalid values.

Hope this is helpful.

Upvotes: 4

Danny Varod
Danny Varod

Reputation: 18118

You can:

  1. Use the class/test init to raise a blank DB or a copy of small DB with a known set of data.
  2. In the test method enter test data (if the DB is empty), then perform the query, then compare result with expect result.
  3. In the test/class cleanup remove DB.

This tests your unit but is considered an "integration test" by some. - The term "unit test" has some disagreement due to the ambiguity of the term "unit".

You could also use an in-memory DB or an in-process DB to make the test environment simpler.

Upvotes: 1

maple_shaft
maple_shaft

Reputation: 10463

You might want to try looking at DbUnit for running unit tests on your data access layer. It puts your database in a known state between test runs preventing corruption of your test database.

Upvotes: 1

John Saunders
John Saunders

Reputation: 161821

In general, there's nothing "wrong" about using TDD to test database code. However, you might try abstracting out the database code, then mocking it out.

Upvotes: 6

Related Questions