I read an article recently which said that mock objects are often misunderstood and misused. Are there any clear mocking anti-patterns which I can look out for?
|
|
It might sound obvious, but: Don't use mock objects in production code! I've seen more than one example where production code depended on the characteristics of certain mock objects ( |
|||||||||||||||||||
|
|
I find that tests which utilise mocks across multiple layers of an application particularly difficult to decipher and change. However I think this has been mitigated in recent years by improved mock framework API's (I use JMock where convenient). 5 or 6 years ago API's like EasyMock were powerful but very cumbersome. Often the test code that made use of it was orders of magnitude more complicated than code it was testing. Back then I tried to influence teams I was in to use it very sparingly and make do with simple handcrafted mocks that were simply alternate implementations of interfaces specifically for testing. Recently my strong opinions on this have become softer as the mocking API's have made tests that utilise them more readable. Essentially I want my code (including tests) to be changeable by other developers without making them feel like they're sifting through a mire of obscure API calls. |
|||
|
|
|
I hate to see simple concrete classes mocked away. For example take the following simple class which has no dependencies on anything else:
In any tests involving this class I'd much rather a real one was instantiated and used rather than some interface like 'IPerson' being pulled out, a mocked one used and expectations set on the . By using the real one your test is more realistic (you have the parameter checks in place and the real implementation of the 'Name' property). For a simple class like this you aren't making your tests slower, less deterministic or muddying the logic (you aren't likely to need to know that Name was called when testing some other class) - which are the usual reasons for mocking/stubbing. As an extension to this I've also seen people write tests where the mock is set up with an expectation, then the mock is called directly in the test. Unsuprisingly the test will always pass...hmmmm... |
|||||||
|
|
In my opinion it's the excessive method invocation check on mocks. I feel that this is a practice enforced by a few mocking frameworks like EasyMock, where the default mock behavior is to fail whenever there is an additional method invocation that what wasn't exactly specified before. This kind of strict mock method checking can lead to brittle designs where the tiniest change to the code can lead to a whole suite of tests failing, even though the core functionality is still the same. A solution to this is starting to use stubs instead of mocks. An article I've found particularly enlightening about the subject was one found in Mockito's Javadoc: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html (see "2. How about some stubbing?"), linking to: http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/. I've enjoyed working with Mockito so far because it does not enforce this strict mocking behavior but the use of stubs instead. It also enforces method checking on specific ones instead of the whole mock object; so you end up checking only methods that really matter in your test scenario. There are a few books here and there I can recommend that touch this subject and mocking and general: xUnit Patterns The Art of Unit Testing: With Examples in .Net Next Generation Java Testing: TestNG and Advanced Concepts (this book is mostly about testNG but there's a nice chapter about mocking) |
||||
|
|
I have observed few anti-patterns in my experience.
Otherwise my experience with mocks especially Mockito has been a breeze. They have made tests very easy to write and maintain. GWT view/presenter interaction testing is much more easy with mocks than the GWTTestCase. |
|||
|
|
