3
votes

I am attempting to do TDD right ! I was reading about the TDD Inside Out as opposed to Outside In. Reason being is that i don't know how my layers up front so my idea was to start writing a test, have it fail and then start writing my first layer.

While writing my first layer I notice that I need another layer, lets call it a service layer. This is where I get confused, what do I do here ?

Do I stop and create a new Test that fails so that I can implement my new service layer using TDD? Once done, I go back to my original layer and should I create a mock of my service layer here ? Or use the service layer I just create via TDD?

This is TDD right ? So if I am mocking things out then maybe my TDD is not driving my development ? But of course if I don't mock things out, these technically are not unit tests but more of integration tests ?

If indeed my unit tests (written via TDD) use mocks then I need to have some other kind of tests to test the integration of each individual layer as one unit ??

An integration test or e2e test?

I think my problems are basically when I need to introduce new layers, should I mock these out, should I create a new test to drive the development of this new layer?

I hope somebody can help with untangling this muddle I have myself in !

Thanks

2

2 Answers

4
votes

With more experience , you will become better with that. But for now let me say this.

First of all, think about TDD as a tool to design clean code (check Uncle Bob's Clean Code to get more insight.). By no means it replaces any system design efforts. That means that you have to know what you want classes to design (at least roughly) and you have to define interfaces between those classes as well.

Second, unit tests according to Mike Cohn - Working Effectively with Legacy Code - Chapter 2 are tests that do not:

  1. talk to a database
  2. communiating accross a network
  3. touching the file system
  4. require you to do special things with your environment to run.

So, you should be well in the limits of a unit test.

In general, you want to write unit tests for each component (or class). That means you create fake classes or mocks for each of the interfaces, e.g. for each of your service layer classes. This means that you have to know the exact interface (method parameters and return value) that each of the call needs. Try to get as far as possible with one instance and then move on to the next.

If you are unsure about how your design has to look like, consider building an untested prototype. Just as much code so you see the components working together and to help build your interfaces. Then sketch down the design, throw away your prototype and start over with a TDD approach.

1
votes

When developing in TDD style you should work with interfaces as much as possible.

Unit testing means that you test every unit isolated from most (ideally all) other code.

So in your case: if the code you currently work on needs to make calls to some service layer. then jsut create an interface for the new modules and mock their correct behaviour (or expected error behaviour if you want to test error handling).

... and put testing your new service layer on your todo list ;)

This way you concentrate your work on your current unit and have an interface ready for your service layer, when you start working on this.

if you want to test how your layers work together, you need some kind of integration test.