How to do TDD correctly? When do I write tests for layers deeper than the business logic layer (i.e. DAL)


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…

Best Solution

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.

Related Question