InfoQ

InfoQ

News

My Bookmarks

Login or Register to enable bookmarks for unlimited time.

The content has been bookmarked!

There was an error bookmarking this content! Please retry.

ObjectMother - a Forgotten Testing Tool

Posted by Amr Elssamadisy on Aug 07, 2007

Sections
Process & Practices,
Architecture & Design,
Development
Topics
Agile ,
Software Testing
Tags
Testing ,
TDD ,
Mocks

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?
  • This article is part of a featured topic series on Agile

Related Sponsor

In today’s hyper-competitive world, later may be too late to adopt Agile development and this Roadmap for Success will help you get started. Download "Agile Development: A Manager's Roadmap for Success" now!

Workaround for xUnit limitations by Alex Popescu Posted
Re: Workaround for xUnit limitations by Amr Elssamadisy Posted
Re: Workaround for xUnit limitations by Alex Popescu Posted
Re: Workaround for xUnit limitations by Amr Elssamadisy Posted
Re: Workaround for xUnit limitations by J. B. Rainsberger Posted
Re: Workaround for xUnit limitations by J. B. Rainsberger Posted
Mixing Mocks and ObjectMother test in real life by Jakub Nabrdalik Posted
Re: Mixing Mocks and ObjectMother test in real life by Amr Elssamadisy Posted
  1. Back to top

    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

  2. Back to top

    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.

  3. Back to top

    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.

  4. Back to top

    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.

  5. Back to top

    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

  6. Back to top

    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

  7. Back to top

    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.

  8. Back to top

    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?

Educational Content

New-age Transactional Systems - Not Your Grandpa's OLTP

John Hugg discusses high volume transaction processing applications with high and low frequency profiles, and how VoltDB can be used for that purpose.

Cool Code

Kevlin Henney examines code samples to see what can be learned from them starting from the premise that one won’t write great code unless he knows how to read it.

Collaboration: At the Extremities of Extreme

Jason Ayers share the observations he made watching a team of developers collaborating in real time on the same code base, pushing XP, pair programming and continuous integration to their extremes.

Yesod Web Framework

Michael Snoyman presents Yesod, a web framework written in Haskell and containing a web server, templating, ORM, libraries (templating, gravatar, etc.).

Transactions without Transactions

Richard Kreuter and Kyle Banker on how to avoid classical RDBMS transactional systems by using compensation mechanisms, transactional messaging or transactional procedures.

Attila Szegedi on JVM and GC Performance Tuning at Twitter

Attila Szegedi talks about performance tuning Java and Scala programs at Twitter: how to approach GC problems, the importance of asynchronous I/O, when to use MySQL/Cassandra/Redis, and much more.

10 tips on how to prevent business value risk

One category of risk that project teams need to ensure they address is business value failure – delivering a product that fails to provide value for the business investor.

Interview: Software Systems Architecture: Working With Stakeholders Using Viewpoints and Perspectives

InfoQ spoke to the authors of Software Systems Architecture on a couple of new topics, the System Context viewpoint and Agile, which have been added to the second edition.