There is an ongoing discussion about TDD and Rails. It was recently
heated by some some of the DHH statements in his RailsConf keynote and
in the blog post: http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html
One aspect of this discussion is the confusion about - What makes a good Unit?
In the Rails community, I've seen people overusing mocks and stubs - you can detect it by looking at all the "should_receive" calls in the codebase. They're not always bad, but they might be potential code smells.
The reason we use should_receive is in a way to draw the boundary between what's important to test right now and what's outside of the test scope.
Let's take an example - you've got an Order, which can have many OrderLines, a ShippingAddress and a Customer.
Do we have 4 units here, representing each class? It depends, but most likely it may be easier to treat the whole thing as a Unit. You can write a test which test the whole thing through the Order object. The test is never aware of the existence of the ShippingAddress. It's an internal implementation detail of the Order unit.
A class doesn't usually make a good Unit, it's usually a collection of classes that is interesting.
This way of defining a Unit gives you tests, that don't need to change whenever the internals change - that's a good thing. You don't want to change tests on every refactoring - in fact it's a smell.
Some time ago, I wrote a surprisingly popular post: The four architectures that will inspire your programming in which I listed:
- Hexagonal Architecture
- Clean Architecture
Clean Architecture has the concept of use-cases which touch the topic slightly differently (by operations, not units), but overall it's very similar: http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
Hexagonal Architecture is all about a Unit surrounded by adapters, in my interpretation. They often call it the Middle Hex. http://alistair.cockburn.us/Hexagonal+architecture
Last, but not least - DCI. This architecture deserves a special mention here. DHH quoted James Coplien in his TDD talk. James has been famous not only from his strong opinions on TDD, but more from his activity in the DCI world. He's one of the fathers of this movement. DCI is the most inspiring architecture here. Ruby and DCI makes a fantastic combination, however not all can work as in the DCI theory. DCI gives good tools for defining what a Unit can be. In short, their approach to what a Context is, may be used to defining Units. A Unit is this paradigm is a collaboration of objects. Read more here: http://fulloo.info/
Have fun in researching more!
If you want to follow more of my work - I'm writing a book on Refactoring Rails apps, which is already available. At the moment, I'm writing new chapters on how to write tests that support refactoring of Rails apps.