views:

125

answers:

4

Hi,

I've set up unit tests that test a fake repository and tests that make use of a fake repository.

But what about testing the real repository that hits the database ? If this is left to integration tests then it would be seem that it isn't tested directly and problems could be missed.

Am I missing something here?

+3  A: 

Well, the integration tests would only test the literal persistence or retrieval of data to and from the layer of persistence. If your repository is doing any kind of logic concerning that data (validation, throwing exceptions if an object isn't found, etc.), that can be unit tested by faking what the persistence layer returns (whether it returns the queried object, a return code, or something else). Your integration test will assure you that the code can physically persist/retrieve data from persistence, and that's it. Any sort of logic to test ought to belong in a unit test.

Sometimes, however, logic could exist in the persistence layer itself (e.g. stored procedures). This could be for the sake of efficiency, or it could merely be legacy code. This is harder to properly unit test, as you can only access the logic by getting to the database. In this scenario, it'd probably be best to try and move the logic to your code base as much as possible, so that it can be tested more easily. There probably exist unit testing frameworks for scenarios such as these, but I'm not aware of them (merely out of inexperience).

Secret Agent Man
+1  A: 

Can you set up a real repository that tests against a fake database?

Regardless of what you do, this is integration testing, not unit testing.

Greg Hewgill
A: 

I'd definitely suggest integration tests against the DAL, within reason.

We don't use the Repository pattern per se (to our chagrin), but our policy for similar classes (Searchers) is as follows:

  • If the method does a simple retrieve from the database using an O/RM call, don't test it.
  • If the method uses query-building features of the O/RM, test it.
  • If the method contains a string (such as a column name), test it.
  • If the method calls a stored procedure, test it.
  • If the method contains logic, test it. But try to avoid logic.
  • If the method bypasses the O/RM and uses raw SQL, test it. But really try to avoid this.

The gist is you should know your O/RM works (and hopefully has tests), so there's no reason to test basic CRUD behavior.

You'll definitely want a "test deck" - an in-memory database, a local file-backed database that can be checked into source control, or (if you have to) a shared database. Some testing frameworks offer rollback facilities to restore the database state; just be careful if you're hitting multiple databases in the same test or (in some cases) if you have embedded transactions.

EDIT: Note that these integration tests will still test your repository in "isolation" (save for the database). All your other unit tests will use a fake repository.

TrueWill
A: 

I recently covered a very similar question over here.

In summary: test your concrete Repository implementations if there's value in doing so. If you are doing something complex in your implementation, it is probably a good idea to test it. If you are using an ORM with no custom logic, there may not be much value in writing tests at that level.

Mark Seemann