Over Mocking
I have noticed using more mocks lately. Instead of using them sparingly for controlling services which are not instrumental to what I am testing, I am essentially using them as a way to isolated what I am testing. This has me noticing a side effect I am not entirely comfortable with. To use the mock, I need to be able to have the mock in the production code, which means I need to inject an abstraction of the mock (dynamic mocks will do that for you).
So, the side effect is long parameter lists, specifically in constructors. Everything takes almost all the objects it uses. Then, to create the production objects are factories. I am using many more factories than I would without mass mocking. I am not sure if this is a good use of dependency decoupling and factory building as design techniques, or if this is a symptom of over design and tightly coupling the mocks to the tests, making it more difficult to change the tests without changing the interface the mock is implementing. Thoughts?
!commentForm
Try poor man's dependency injection: have a constructor that allows you to inject your dependencies (hidden behind interfaces) for testing, then have a default constructor that instantiates the concrete objects and injects them itself.
I don't think mocks or factories are the real problem here. If A depends on the services of B,C,D,E,F,G,H and I, then it's depending on too many things whether you inject the objects or instantiate them internally.
Don't "inject" dependencies. Mock an object's peers in tests and pass real peers to it's constructor or as method arguments. Composite objects should create objects they use internally and not expose them at the constructor. A composite object should be simpler than the sum of its parts. Also, avoid passing all dependencies into an object's constructor: you can probably pass collaborators as method arguments, not constructor arguments.
The smell of a long parameter list leads me to think you may be able to collapse some objects behaind a coarser-grained interface.
I find using a DI container like PicoContainer[?] eases the pain by making all (or most of) those factories unnecessary.
I'm still not happy about the long parameter lists in constructors, so I think I will give a few of the suggestions above a try. Thanks all.
I'm still not happy about the long parameter lists in constructors, so I think I will give a few of the suggestions above a try. Thanks all.
Personally I mock whatever and whenever I can. Usually a hardship with mocking reveals some interesting deeper design problems. If there are too many arguments for constructor it probably means the class under test has too many dependencies, which means a problem with cohesion. In my experience I seldom need to mock more than 5 interfaces per test case. It's usually one or two as constructor arguments and two, max three for returned objects. If it's more I try to re-factor.
"In my experience I seldom need to mock more than 5 interfaces per test case."
Do you only mock interfaces?
Do you only mock interfaces?
In the large (8000+ classes) J2EE web app I am currently working, many business classes obtain instances of other business classes by simply instantiating them with the "new" operator. Besides being the simplest way to obtain dependencies, this allows business service classes to maintain client-specific state, so that private methods don't need to have any parameters.
Of course, with the mock objects tools previously available, it would have been difficult to unit test such classes. But I wanted to use "new", and also have final classes, final methods, and static methods where appropriate.
So, with that "itch to scratch", I went ahead and created a new tool that would free me to design the application without constraints, and still have complete unit tests.
If anyone wants to give it a try, the tool is here: jmockit.dev.java.net.
Of course, with the mock objects tools previously available, it would have been difficult to unit test such classes. But I wanted to use "new", and also have final classes, final methods, and static methods where appropriate.
So, with that "itch to scratch", I went ahead and created a new tool that would free me to design the application without constraints, and still have complete unit tests.
If anyone wants to give it a try, the tool is here: jmockit.dev.java.net.
"Do you only mock inerfaces?" Not only, but I prefer so. In C++ it really doesn't matter since there is no good mock library (I use my own which is based on link time substitution; I plan to sourceforge it soon). In Java and C# interfaces do not cost too much, but sometimes you have a class comming from the infrastrucure. You would like to mock it but you do not want to wrap it with an extra interface. For example I recently mocked Java's TimerTask[?]::cancel in order to validate that in a certain scenario a timer cancellation request is sent properly. I also do test what will my program do if the TimerTask[?]::cancel returns false (too late to cancel).
Add Child Page to OverMocking