BT

ObjectMother - a Forgotten Testing Tool

by Amr Elssamadisy on Aug 07, 2007 |

One of the earliest techniques for writing tests using TDD did not use mocks and stubs, but used the actual business objects instead. By creating a set of factories that instantiated, composed, and executed methods on business objects, real objects, in a non-initial-state of their lifecycle, could be created for testing purposes. The name coined for this pattern was ObjectMother.

This technique has never caught on as widely as mocks and stubs, but it has never died out either. Developers are rediscovering it constantly when they start to feel that mocking/stubbing is too difficult because of breaking dependencies, or fragile because they are a form of duplication that must be maintained in parallel to the real business objects.

JB Rainsberger used this type of solution for testing a Rails application in preparation for XP Day Toronto 2007. Maarten Winkels considers ObjectMother a viable alternative when testing the Data Access Layer. And Vikas Kerni dropped mocks because he felt they were too much overhead and ended up using ObjectMother instead.

At the same time, many consider ObjectMother a bad idea, or even an anti-pattern because of its (mis)use. J. Richardson left this comment on the c2 wiki page for ObjectMother:

Actually this should be called an AntiPattern. In practice all those I've seen that have advocated this approach return shamefaced a few months later. This pattern is a bit like the other well known pattern "putting everything in one place", and what it is that is actually being created is quite non-obvious. A Builder pattern might be more useful...
In the end, ObjectMother is one more tool in the testing toolbox. What is your experience - is it worth using and if so, in what context? Or is it dangerous and evil - and if so, why?

Hello stranger!

You need to Register an InfoQ account or to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Workaround for xUnit limitations by Alex Popescu

After reading the original paper on ObjectMother, I have the feeling that this is just another workaround for the xunit limitations: namely the fact that test method cannot receive parameters.

TestNG has addressed this missing feature long time ago by providing different mechanisms to pass parameters to test methods: either static or dynamic. And the ObjectMother synonim is DataProviders.
And yet another benefit of the way TestNG solves this problem is the one addressed by IoC/DI solutions (injection vs factory usage).

bests,
./alex
--
.w( the_mindstorm )p.
________________________
Alexandru Popescu
Senior Software Eng.
InfoQ TechLead&CoFounder

Mixing Mocks and ObjectMother test in real life by Jakub Nabrdalik

I'm using TDD for about three years now and I've started with mock objects.

As configuring mock objects (or the mock environment for a tested class) started to take way too much time (above half an hour), we started to use ObjectMother (giving test configuration with real classes and real DB) to create the environment for a tested class.

The disadvantage was obvious - these were not real UNIT tests anymore, more like integration tests mixed with unit tests. In real life, however, when using ObjectMother only when the class configuration with mocks is painful (like for example service layer) it works great. The only real disadvantage is that those tests tend to run slow (since you're using real database and other layers). Unfortunately this is quite important.

The advantages are that writing such a test is a snap and that changing the inner behavior of a class does not require changing of a test (which is typical if you're expecting something with mocks).

The work-around for sluggishness of those tests is to divide all the test into two sets: fast (working with mocks) and slow (working with ObjectMother). You can run the fast set of tests every moment and you can run the slow set when you think the code is done or nearly done (to check if you've not screwed up something with your changes).

When having a big solution with multiple projects based on each other (say: [Framework -> CMS -> Portal] or [Framework -> Abstract Shop -> Dedicated implementation of a shop]) I tend to use mocks for the low level projects (framework) and ObjectMother for heavy service layer objects of top-level project. This way the core tests are fast and the final product tests are simple and stable.

Re: Workaround for xUnit limitations by Amr Elssamadisy

I would disagree - it has nothing to do with xUnit.

The project being described was a large leasing application and the most complex objects had objects, that contained other objects, that etc... They had to be setup 'just right' for a correct test with correct tax parameters, dates, and as the assets depreciated over time, they had to depreciate correctly.

Putting all of that in a mock to check a correct calculation is code duplication at its worse. Therefore, the team opted towards and built an extensive set of factories that would create and move objects accross their lifetime.

For example, they would create a lease in Ohio (special tax laws), add 5 assets, and then age the lease for 5 years (because the calculations involving the $ amount would require code duplication in the setup function that rightly belongs in the domain objects).

So - no, it has nothing to do with xUnit at all. It has everything to do with mocks being a form of code duplication.

Re: Mixing Mocks and ObjectMother test in real life by Amr Elssamadisy

I've found many people who do just this - mix mocks and objectMother. One common scenario is to use objectMother inside a layer (domain/service/mapping) and to mock out other layers.

It is true that you no longer have 'unit' tests, they are integration tests by definition. But you focus on the requirements of one class and then exercise that class and its dependent objects.

Re: Workaround for xUnit limitations by Alex Popescu

Well, I am afraid I completely disagree with you :-). I see your point though. Let's look at it this way:
The project being described was a large leasing application and the most complex objects had objects, that contained other objects, that etc... They had to be setup 'just right' for a correct test with correct tax parameters, dates, and as the assets depreciated over time, they had to depreciate correctly.


The process usually goes this way: you start by setting up your object graph ones. Then the 2nd time you need a similar "arrangement" you start refactoring the tests so that they reuse the creation of these object graphs. But oops... you are noticing that you have no injection capabilities in your xunit framework. So, you rely on the last option you have: using the Factory pattern. And create a new buzzword for it: ObjectMother. Otherwise, you would only be following the code reuse rule, which is not a buzzword.

Concluding: I am not arguing against code reuse. This is software development common sense. I am arguing against the need of new buzzwords for simple tasks (and in this particular case the buzzword has to do with the fact that xunit doesn't allow tests to be written as you normally write your other pieces of code).

bests,
./alex
--
.w( the_mindstorm )p.
________________________
Alexandru Popescu
Senior Software Eng.
InfoQ TechLead&CoFounder

Re: Workaround for xUnit limitations by Amr Elssamadisy

:)

ObjectMother may be considered a 'buzzword', but aren't all patterns? They are vocabulary to indicate a common solution to a common problem within context.

ObjectMother is not just a factory. It is a factory plus an engine to move the objects to a particular state in their lifecycle. The word ObjectMother replaces the sentence. (I noticed you didn't object to the use of factory instead of saying "a class whose responsibility is creating other classes.")

Injection is a wonderful thing because the factories are given to us by the framework instead of hand-written, but they are only half of the solution.

Amr

Re: Workaround for xUnit limitations by J. B. Rainsberger

You've missed the point, Alex. ObjectMother is not a way to feed data to a test; it is a way to hide constructor details and avoid irrelevant details in a test. You have this problem whether your test method accepts parameters or doesn't.

For example, I was working with code this week that required creating a Book with an ID, title, and genre. In one test, only the ID was used to determine the expected result, and the title and genre could be anything. For that test I created a Book this way: new Book(12, "irrelevant detail", "irrelevant detail"). These parameter values are irrelevant for the test, so I marked them that way.

Now, when it's time to write tests that need the title, but not the genre, I have to repeat the genre value "irrelevant detail". When I write a test that needs the genre, but not the title, I have to do the reverse.

I can hide the detail by writing MyTest.newBookWithId(12) and avoid the question of "what's the title? what's the genre?" I benefit for many reasons that I'm sure you find obvious: less impact when changing the Book constructor, removing noise from the test, that kind of thing. This is the beginning of an ObjectMother. When I have many of these methods and I move them from the test classes to a central test data creation class, I call that the ObjectMother for Book objects.

Don't get me wrong: I understand your desire to promote TestNG, but I'm not sure it's helpful to promote a feature of TestNG that brings little to bear on the problem under discussion.

Re: Workaround for xUnit limitations by J. B. Rainsberger

Why is it that every time we name something, it's a buzzword? Can't it just be a name? Is "Alex" a buzzword?

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

8 Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2013 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT