Mark Needham

Thoughts on Software Development

TDD: Hand written stubs vs Framework generated stubs

with 8 comments

A few months ago Uncle Bob wrote a post about TDD where he suggested that he preferred to use hand created stubs in his tests wherever possible and only resorted to using a Mockito created stub as a last resort.

I’ve tended to use framework created ones but my colleague Matt Dunn and I noticed that it didn’t seem to work out too well for us writing some tests around a controller where the majority of our tests were making exactly the same call to that repository and expected to receive the same return value but a few select edge cases expected something different.

The edge cases came along later on by which time we’d already gone past the stage of putting the stub expectation setup in every test and had moved it up into a setup method which ran before all test.

We tried to keep on using the same stub instance of the dependency which meant that we were trying to setup more than one stub expectation on the same method with different return values.

[TestFixture]
public SomeControllerTests
{
	private ITheDependency theDependency;
 
	[SetUp]
	public void Before()
	{
		theDependency = MockRepository.GenerateStub<ITheDependency>();
		theDependency.Stub(t => t.SomeMethod()).Return(someResult);
 
		controller = new Controller(theDependency);
	}
 
	....
 
	[Test]
	public void SomeAnnoyingEdgeCaseTest()
	{
		theDependency.Stub(t => t.SomeMethod().Return(someOtherResult);
 
		controller.DoSomething();
 
		// and so on...
	}
 
}

We were struggling to remember where we had setup the various return values and could see a few ways to try and reduce this pain.

The first was to extract those edge case tests out into another test fixture where we would setup the stub expectation on a per test basis instead of using a blanket approach for all of them.

This generally works pretty well although it means that we now have our tests in more than one place which can be a bit annoying unless you know that’s what’s being done.

Another way which Matt suggested is to make use of a hand written stub for the tests which aren’t bothered about the return value and then use a framework created one for specific cases.

The added benefit of that is that it’s more obvious that the latter tests care about the result returned because it’s explicitly stated in the body of the test.

We found that our tests were easier to read once we’d done this and we spent much less time trying to work out what was going on.

I think framework generated stubs do have thier place though and as Colin Goudie points out in the comments on Uncle Bob’s post it probably makes more sense to make use of a framework generated stub when each of our tests returns different values for the same method call.

If we don’t do that then we end up writing lots of different hand written stubs which I don’t think adds much value.

I still start out with a framework generated stub but if it’s becoming overly complicated or repetitive then I’m happy to switch to a hand written one.

It’d be interesting to hear others’ approaches on this.

Be Sociable, Share!

Written by Mark Needham

January 15th, 2010 at 9:44 pm

Posted in Testing

Tagged with

  • Pingback: TDD: Thoughts on using a clock in tests at Mark Needham

  • http://www.davidron.com David Ron

    I’m not familiar with Mockito, but I use jMock quite frequently. I often find myself writing:

    @Test
    public void testSomething(){
    expectSomethingWillHappen()
    service(findFromList(someList));
    }

    @Test
    public void testSomethingElse(){
    expectSomethingWillHappen()
    service(findFromList(differentList));
    }

    private void expectSomethingWillHappen(){
    IrrelevantObject dummyObject = new IrrelevantObjectBuilder.build();
    context.checking(new Expectations(){{
    one(dao).findobject(with(any(List.class)));
    will(returnValue(dummyObject));
    }});
    }

    This pattern works really really well, and is a lot more simple than hand-created mocks.

  • Pingback: Tweets that mention TDD: Hand written stubs vs Framework generated stubs at Mark Needham -- Topsy.com

  • Pingback: Helltime for January 18 « I Built His Cage

  • http://giorgiosironi.blogspot.com Giorgio Sironi

    I think using generated Test Doubles is a symptom that abstractions are efficient, as their method’s behavior is forced to be simple. That said, often hand written stubs are more expressive.

  • http://www.truewill.net/myblog/index.php Bill Sorensen

    You could skip the Setup and fields and have a method that returns a controller (or a dependency, then create the controller in the test methods). Adjust as needed for your cases and add new methods as needed. Basically refactor your unit tests to remove duplication.

    private Controller GetController(int dependencyResult)
    {
    ITheDependency theDependency = MockRepository.GenerateStub();
    theDependency.Stub(t => t.SomeMethod()).Return(dependencyResult);

    return new Controller(theDependency);
    }

  • Pingback: TDD: Simplifying a test with a hand rolled stub at Mark Needham

  • miluch

    Provided “We tried to keep on using the same stub instance of the dependency” you ended up using 2 references: hand rolled stub and framework mock.
    I always try to make my test method self descriptive and try to avoid using setup methods. Following this, if i find that my test method become bloated with setup code i try to refactor it into seprate builder method/classes