One thing I noticed, ever since I got the hang of mocking, is that like anything, there is such a thing as too much of a good thing!
I started writing out my code decoratively, using unit tests to define the behavior expected of the production code. Next, I wrote the production code that would fulfill these expectations. And the test would go 'green'. All was good.
Or so I thought.
As the system grew, and I found myself refactoring code that was under the test harness, I spent more and more time fixing tests that failed because the production code ceased to behave as expected!
Oddly enough, the assertions, and thus the actual, final results of the tests were unaffected.
I realized that there was a pattern here. I was testing behavior, when I really cared about state.
My conclusion was this: If I'm testing a unit within the system, i.e. depending entirely on more code of my own (or on nothing at all), I should test state (i.e. make assertions about the results).
Otherwise, if I can't test the result of the code (i.e. a void method), or I'm at the system boundary (i.e. depending on code that is not part of my system), then - and only then - should I mock that dependency, and test for behavior (i.e. make sure that a dependency gets called).
But what if I have a dependency that I want to fake it's result? Use a stub. Your favorite mocking framework has mock-like constructs, that do not raise exceptions if the expectation fails. Those are called Stubs. Otherwise, use simple inheritance to fake a class and spoon-feed the return values.
There. That makes sense.
Now go, loosen up that strict behavior management.
It's okay. I can wait.
יום חמישי, 30 באפריל 2009
הירשם ל-
תגובות לפרסום (Atom)

0 תגובות:
הוסף רשומת תגובה