A while back I read Kent Beck's book Test-Driven Development By Example and in it I admired the concise elegance of Kent's style in writing unit-tests.
Later I looked at Rod Johnson's Spring framework http://www.springframework.org/index.html which seems to rely on EasyMock, which is built on MockObjects, and was pondering how different authors take such seemingly different approaches to writing unit-tests.
Do you have an opinion about whether MockObjects/EasyMock adds alot of undesirable library-bloat? If not, do you think Kent limits himself by (seemingly) not using these tools that run on top of his Junit tool?
I certainly do have an opinion: the use of mock objects does not lead to any kind of bloat, although it may uncover areas of a design that could be simplified.
I have done some informal research into what Eric Armstrong called "test-driven refactoring". This is choosing refactorings by looking at the complexity of the /tests/, rather than just the complexity of the production code. The idea is that if a testable design is a good design, then if we simplify the tests, we likely simplify the design of the production code.
Now I used EasyMock generously throughout JUnit Recipes, and mentioned jMock, which I am looking for an opportunity to practice with. I have the tendency to mock early, mostly because I'm still in the learning phase--I want to see what designs this approach leads me to, and so far, I'm quite pleased with the results.
Regarding Kent Beck's testing style in TDDBE, I have to point out that virtually nothing in those examples motivates the use of mock objects. The Money class does not connect to any expensive, external resources, so there's not much point in substituting production implementations for their mock counterparts. I have not had the chance yet to work with Kent on an enterprise-calibre application, so I don't know what he would do when faced with a database, network connections or somesuch; however, from what I've read, he would use fakes/stubs/mocks there, just like I would.
Author of <a href="http://www.amazon.com/exec/obidos/ASIN/1932394230/ref=jranch-20" target="_blank" rel="nofollow">JUnit Recipes: Practical Methods for Programmer Testing</a>
We just came across a real need for mock objects in our testing being that our group is slightly ahead of another. EasyMock was mentioned as a tool, but I have also come across a mockobject tag when using XDoclet. I've always mocked my objects by hand and am new to both of these tools. I welcome opinions on both. Thanks.
There's a fundamental difference between the approach of EasyMock/jMock and MockObjects. EasyMock and jMock are based on behavioral testing (the "mock objects" you create with these utilities can be used to verify that the class under test collaborates with the mocks as expected) while MockObjects and other "static" mock object libraries are based on state-based testing (you verify the resulting transitions in the mocks' state instead of how they got there). Both have their merits and both have their flaws.
Originally posted by Lasse Koskela: Both have their merits and both have their flaws.
Or, perhaps more correct, both have their uses in different situations.
I mostly use EasyMock for simple mocks of Observers and the like. The MockObjects library, I would say, is mostly usefull for more complex mocks, especially the predefined ones like the JDBC mocks.
The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Originally posted by Jeanne Boyarsky: How do you find MockObjects to be better for more complex/predefined objects? Is it due to less setup code or something else?
Yes, due to less setup. This is more a good guess than educated opinion, though, as I don't find myself often in a state where I need complex mocks (actually, I prefer to refactor the code away from such situations).
Originally posted by Lasse Koskela: ... MockObjects and other "static" mock object libraries are based on state-based testing (you verify the resulting transitions in the mocks' state instead of how they got there). ...
I'm sure you know more than I, but it seems to me that conventional mock objects are not limited as you described, and are used in a collaborative way. Reference page 254 of JUnit in Action, for example, which not only suggests dynamic behavior but even passes the mock object around. I don't know anything about the other mock utilities, so I can't say if the distinction is really what you described. Thanks for your words of wisdom, however. [ August 11, 2004: Message edited by: john prieur ]
Juan Rolando Prieur-Reza, M.S., LSSBB, SCEA, SCBCD, SCWCD, SCJP/1.6, IBM OOAD, SCSA
J. B. Rainsberger
Joined: Aug 05, 2004
Here is what a mock object does:
1. You use it in a test to replace a more expensive, difficult-to-use object. 2. You set expectations on the mock object about how you expect it to be used. 3. You use the mock object in your test. 4. You ask the mock object to verify itself, meaning, check whether it was used according to the expectations you had set.
A mock object can replace an expensive, external resource--like a database--to make your tests execute much more quickly (100 per second, instead of 1 per second). A mock object also helps you focus on the interactions between objects, rather than the implementation details of the objects you're not testing at that moment.
Joined: Jan 23, 2002
John, I'm referring to the trade-offs discussed (for example) in Martin Fowler's Mocks Aren't Stubs article.