Mark Needham

Thoughts on Software Development

Test Doubles: My current approach

with 6 comments

My colleague Sarah Taraporewalla recently wrote about her thoughts on test doubles (to use Gerard Meszaros‘ language) and it got me thinking about the approach I generally take in this area.

Stub objects

I use stubs mostly to control the output of depended on components of the system under test where we don’t want to verify those outputs.

Most of the time I make use of the mocking library’s ability to stub out method calls on these dependencies.

I find that it generally seems to require less effort to do this than to create hand written stubs although chatting to Dave about this he pointed out that one situation where it would make more sense to use a hand written stub is when stubbing out a clock/time provider. This is because there are likely to be multiple calls to it all over the place and most of the time you probably want it to return the same value anyway.

I actually quite like the fact that you need to specify all the stub calls that you want to make in each test – it helps you to see when you have too many dependencies and then hopefully you can do something about that.

On previous projects I worked on we decided the way to get around that problem was to define all the stub method calls in a setup method but that seems to lead to a world of pain later on when you forget that you’ve stubbed a method in the setup and now want to assert an expectation on it or (to a lesser extent) write a test which doesn’t actually use the stub.

Fake objects

I often confuse fakes with stubs as seem to be quite similar to each other in their intent – the difference as I understand it is that with a stub we are controlling the output of a dependency whereas a fake just sits there and lets interactions happen with it. The values passed in earlier calls to the fake may be returned in later calls to it.

The most common use of this pattern is to replace a real database with a fake one for testing although on a recent project we were making use of a hand written fake session store to avoid having to refer to the real session in our test code.

We might have one call to the ‘SessionFake’ to store a value and then if a retrieve call is made later on we would return the value that we previously stored.

The approach Sarah describes for stubbing repositories seems quite similar to this as well.

Mock objects

I use mocks to replace depended on components of the system under test when I do care about the way that is is used i.e. we want to verify the behaviour of the dependencies.

If we see a mock object being created in a test then we should see a call to a ‘verify’ method later on to ensure that the expected methods are called on it.

I used to use these all over the place for just about every test where I wanted to control the way that a dependency acted until I realised how fragile and confusing that made the tests.

Now, after recently watching a presentation by Jay Fields, I try to ensure that I’m only setting up one expectation per test and use of the other test double approaches for any other dependencies that needs to be taken care of in that test.

Dummy objects

Most of the time when I pass dummy values into tests they tend to be strings and I prefer to pass in a value of ‘irrelevantValue’ rather than just passing in a null which may lead to difficult to locate Null Pointer Exceptions further down the line if the value which we thought was just a dummy starts being used.

We are generally only passing in these dummy values to satisfy the requirements of the system under test which may require values to be entered even if the particular piece of functionality that we are testing doesn’t make use of them.

Overall

I think my current approach to testing leans more towards mockist rather than classicist although I think I am probably moving more towards the middle as I see the problems we can run into with over mocking.

With test doubles my current approach has minimising the effort required to create them as the most important aspect but I’m sure that will change given a different context. With all the test doubles I generally try and use test data builders where it’s not overkill.

Be Sociable, Share!

Written by Mark Needham

July 14th, 2009 at 1:23 pm

Posted in Testing

Tagged with ,

  • Pingback: Reflective Perspective - Chris Alcock » The Morning Brew #389()

  • Hey Mark, good stuff as always. you mentioned you pass strings like “irrelevantValue”. I used to do that as well, but I saw a great presentation by Jeremy Miller (great presentation btw) where he talked about using meaningful test data. Since then I have tried to use values that make sense in the context of the system under test. I find it helps the readability of tests in the long run.

    You can get to a video of the presentation from this blog post if you are interested: http://codebetter.com/blogs/jeremy.miller/archive/2009/05/28/the-joys-and-pains-of-a-long-lived-codebase-the-video.aspx

  • Hi Mark,

    Nice post. My question is: when you explain this to test newbees, does this segmentation help?
    The reason I’m asking is because we (Typemock) found that most people use “mock” for stub anyway, and while the “dictionary” meanings exist, they are not useful for beginners.

    What is your experience?

    Thanks,

    Gil

  • @Robin I actually saw that presentation as well & agreed it’s really good. Maybe I didn’t quite understand the idea about meaningful data…would you aim to pass meaningful data even if that particular piece of data didn’t really matter for the current test?

    @Gil I find when talking about the stuff (with anyone) I refer to stub or mock depending if we’re testing an expectation or not – I don’t think I really got the difference between them until quite recently.

    I still struggle a bit with the difference between dummy & stub so this post was more about me trying to clear up my understanding of whether I actually use each of the patterns even though I probably don’t segment them when using them on projects.

    I guess the dictionary meanings might be useful when working with people who also know them.

  • Pingback: Reading Code: Rhino Mocks at Mark Needham()

  • Pingback: OpenQuality.ru | Июльская лента: лучшее за месяц()