tags:

views:

101

answers:

3

I'm still uncertain about how best to use Mocks when doing development from the outside-in (i.e. write test first that mimics the customer's requirement)

Assume my client's requirement is "Customer can cancel her order".

I can write a test for this - Test_Customer_Can_Cancel_Her_Order.

Using TDD I then write the business class and mock the data access layer (or any layer that is 'deeper' than my business logic layer). Fantastic, my test passes and I am only testing the business layer and not any layers underneath.

Now what I am wondering is... when do I delve deeper and start writing and testing the data access layer? Directly after the top-level test? Only when I write the integration test? Maybe it doesn't matter? As long as it gets done at some point?

Just wondering...

+4  A: 

This is a tricky question. Some people think that it's ok to test "private" code, some people think it's not. It is certainly easier, as you don't have to do complex setups to reproduce an application state that lets you test a small function that you want to add (you can test that function directly). I used to be among those people, but now I'd say that it's better to just test public APIs (create tests and setups that do and see only what the user can do and see). The reason for this is that if you only test public API, you empower yourself with unlimited re-factoring potential. If you test private code, you will have to change your tests if you choose to re-factor (making you less prone to "refactor mercilessly", thus leading to bad code).

However, I have to say, testing only public APIs do lead to more complex test frameworks.

So, to answer to your question more specifically, your next step is to try to think of a situation where there would be a problem with your current order cancellation code and write a new high-level setup to reproduce that problem. You mentioned data access tests. Create a high level setup where the database is corrupt, and test that your application behaves gracefully.

Oh, if for GUI applications, it's a little trickier, as you don't really want to get to the point where you test mouse clicks and read pixels. That's just silly. If you use (and you should) the MVC system, stop at the controller level.

Virgil Dupras
Interesting answer, thanks Virgil.
willem
+1  A: 

Use integration tests for query and other data access testing.

Matt Hinze
So no unit testing at all for your DAL?
willem
nope. just integration tests for that. in each fixture we set up siloed data and test our queries and mappings and cascades, etc. we have something like 3000 unit tests and 300 integration tests. most of those integration tests test the database. we have some infrastructural code (around session management and stuff) that is tested but that stuff is mostly outside our codebase. a few nh classes, like IUserTypes are unit tested.
Matt Hinze
i should probably add that there's a lot more to this. ping me mhinze at gmail if you want to talk more.
Matt Hinze
+1  A: 

I always write tests to test the DAO layer, which isn't testing business logic, but I feel it is important to test the CRUD features. This has gotten me into a lot of trouble because if my database is corrupt for some reason my tests have the high possibility of failing. What I do to prevent these DAO type tests from failing is, first do the testing in a non-production database. Then for each CRUD/DAO test I

  1. find objects that may have been left around from a previous test and if exist I delete them.
  2. I create objects I want to test
  3. I update the objects I want to test
  4. I clean up or delete the objects I created.

This sequence helps me to make sure my database is in a condition where my tests will not fail if run twice and the first time the test stopped half way in between.

Another way is to wrap your CRUD tests in a transaction and at the end of the test rollback the transaction so the database is in the state that it began.

Peter Delaney
Good advice, especially rolling back using a transaction.
willem