What I Did Wrong (Test::MockObject)


I admit it, I avoid languages such as Java because they make it so difficult to write useful libraries such as Test::MockObject. When you're writing lots of test cases and flipping back and forth between code and test code and refactoring every time you make a test pass, the more ceremony and boilerplate you have to move around, the more friction you feel and the less work you can get done easily.

I wrote T::MO several years ago when I noticed a pattern in test code I'd written. I wanted to isolate a couple of cases of behavior to test all of the code paths within specific functions and methods. Invariably I took advantage of Perl's dynamism to construct objects which adhered to a specific protocol of behavior but which were under my direct control.

Think of it this way. You want to test the error handling code for a database abstraction layer. If the network connection goes away or if the remote process crashes, you want to retain the data and perform the appropriate logging and recovery.

How do you test that? You force a failure. No, you don't hire an intern to yank the network cable during your tests. You mock up the code which raises the "Wow, it's suddenly quiet in here!" exception.

This is where I wrote T::MO wrong. Instead of mocking just one piece of the underlying plumbing, T::MO encourages people to mock the entire system, from the faucets down to the sewer system. You do get more control over the process, but you can lose yourself in a sea of sweaty little details.

T::MO can be an invaluable tool. Sometimes it's exactly what you need, especially when you have to clean up a pile of legacy code written without good design taste. Even so, I wish I'd written Test::MockObject::Extends first to encourage people to mock only part of the behavior of an object. If your code is anywhere close to well-factored, you should be able to splice in the specific behavior you need, scalpel precise, and have confidence that the rest of the code, the real code you run when you run the code for real, behaves appropriately.

The more you need to mock, the more coupled (and, generally, the poorer) your design. The less you do mock, the better your tests.


It's not just losing yourself in a sea of sweaty little details; it's the API or logic changing, but the mocked object not knowing this. As a result, someone could alter the foo() method to not return integers less than 3, but if your mock doesn't know this (and in large systems, this is more likely), than your code is not testing what it should be. That's why I've always advocated mocking the smallest possible bit you can in order to minimize this.

That's my long-winded way of saying Test::MockObject::Extends++ :)

Though not very well-versed in object mocking, I'm fascinated by it and the new opportunities it provides for testing things previously untestable.

Does anyone have an example of a CPAN module which does this right? I.e. a module which heeds the advice of this blog post. I think I get what this post is saying, but I'd like to see it in real code as well.

Test::MockObject is a great and very useful module that I have used in testing several projects. What I think is wrong with it is that it uses the UNIVERSAL::isa module (which I believe you also wrote), which modifies perl's core functionality. And there is no option to disable that. Most users of Test::MockObject would not care about this. I noticed it because it causes problems when using Test::MockObject and Test::Class::Sugar, another awesome testing module, together.

I didn't originally write UNIVERSAL::isa, but I have uploaded newer versions.

However, without UNIVERSAL::isa T::MO would have no hope of working reliably. As long as people write buggy code, their bugs will prevent T::MO from working correctly.

Guess who gets bug reports then?

Fortunately, modern releases of Perl 5 explicitly discourage the use of that particular buggy construct, so there's at least some hope of having other people fix their bugs.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

sponsored by the How to Make a Smoothie guide



About this Entry

This page contains a single entry by chromatic published on August 16, 2010 6:49 PM.

Modern Perl: The Book Seeks Comments was the previous entry in this blog.

On Deployment is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by the Perl programming language

what is programming?