views:

191

answers:

3

hello, i have read many articles about unit testing.. Most of the articles said that we should not use more than one mock object in a test..but i can't understand why :s sometimes we really need more than one mock object in a test..

+3  A: 

I'm not sure what articles you're referring to, but I typically have one mock object per dependency for the class under test.

JohnOpincar
+4  A: 

You can have more than one mock in a unit test depending on the context.

However I think what 'the articles' might be hinting at is

  • prevention of over-mocking. When a unit-test mocks out all collaborators, you leave the door open; the scenario might fail when you substitute real collaborators. By minimizing the number of mocks and using real collaborators as far as feasible/possible, you minimize that risk.
  • High Coupling alerts: If you find yourself having to mock lots of collaborators inorder to write a unit test, it might be a design smell indicating that you have high coupling.
Gishu
+1 for the coupling hint. But I wouldn't suggest using "real collaborators" just for reducing the number of mocks. Sometimes you test several classes together, because they are highly coupled and build a component. But everything outside should be isolated as good as possible. The if you find that you have too many mocks, you have a coupling problem. Then you should refactor.
Stefan Steinegger
I recommend using 'real' collaborators not for reducing the number of mocks.. but to make the test mirror real world operation. This is to avoid the case where your test passes because you were playing with a set of mock objects.. however in the real world it fails to work because one of the dependencies now doesn't act/behave like the corresponding mock. If the collaborator doesnt slow down the unit test, creating an interface at the boundary and then using a mock is overkill.
Gishu
@Gishu: I don't agree. Mocks are for isolation, not for speed. You need to isolate the code under test as good as possible, this is like a laboratory test in chemistry, you simplify the environment to isolate a single process. Then you can prove what the process does, independent of an unknown environment. Mocks should be trivial and therefore manageable. Other classes are another unknown. What you are doing is also important, but it is an integration test, which you should do after you proved that the single classes are behaving according to specifications.
Stefan Steinegger
+1  A: 

You should add as many mocks as necessary to isolate your class under test. You need a mock for every dependency that should not be part of the test.

Sometimes you put two or three classes together in a test, for simplicity, because they build something like a component and are highly coupled. Everything else should be mocked.

I know this "best practice" to have only one mock and also do not understand it. In our unit tests, we have many mocks, some environmental mocks are set up by the test framework I wrote (eg. TransactionService, SecurityService, SessionService). There is only one thing to consider, as Gishu already mentioned in his answer, many mocks are an indication of high dependency. It's up to you to consider when it is too much. We have many small interfaces, which requires many mocks in tests.

To turn your answer around, you should not mock a dependency when:

  • It is a highly coupled part of the class under test, like an inner class, private class etc.
  • It is a common .NET framework class like a Collection and the like
  • You want to write an integration test to test exactly the interaction with that class. (You still mock everything else and you still have unit tests for every involved class in isolation.)
  • It is just to expensive to mock a certain class. Be careful with deciding it as too expensive, mocks seem to be hard to set up, but turn out to be a breeze compared to the maintainability problems you'll have with using real classes. But there are some frameworks and technologies that are not implementing against interfaces and are very hard to mock. If it is too expensive to put this framework classes behind your own interface, you need to live with them in the tests.
Stefan Steinegger