October 11, 2005

Unit testing using mock objects

So anybody who has worked with me knows that I am a huge fan of unit testing, and it is not unusual for the amount of unit test code to exceed the amount of code being tested.

Looking back, it appears that most of my unit tests are mainly transparent (white box) and I prefer mocks over stubs.

This was never really a conscious decision, but I am quite comfortable with it. The benefits of white box testing is that you know your code is doing exactly the right thing. For example, the code in Sitebuilder2 that generates the object graph for the site navigation is very expensive, and therefore it is critical that it does the right thing. For example, Page has a method "isPubliclyVisible", which is a simple boolean field. It is essential (for performance) that this is called before doing an expensive webgroups lookup, and this logic is built into the unit tests. Were I to do a black box approach, it could be argued that this logic is absolutely internal and should not be tested.

In order to define these restrictions, I use link to define mocks for any collaborators. Conceptually this is the right thing to do. Stubs would not give me the control I required. On the other hand, a lot more work is required to define your mock objects. JMock also falls down when it comes to refactoring because you describe all your methods using strings.

When would I use stubs? Well, to be honest, very rarely. When should I use stubs? I would recommend using stubs when you truly do not care about how your stub will be used.

One of the unfortunate asides of using jmock to explictly define the allowed method calls is that you can very easily end up having to modify the expectations on objects just because you change a seemingly independant line of code.

For example, assume I have a method on page called addPage(Page). Imagine I know have a unit test for the duplicate method:


  public void testSomething(){
    // some code….

    Mock mockPage = mock(Page.class);
    Page page = (Page) mockPage.proxy();

    HtmlPage sourcePage = new HtmlPageImpl();
    sourcePage.addPage(page);
  }

If I change the Page.addPage(Page) method to automatically set the site, i.e.:


  public void addPage(final Page page){
    getPages().add(page);
    page.setSite(getSite());
  }

then all of a sudden, anywhere I have mocked up a Page which is added to another page will fail. This is a horrible, but unavoidable consequence of using mock objects for which you are expliclty defining behaviour.

Had I used a stub to represent Page, no problem.

So I do firmly believe that mock objects have an absolutely invaluable place, but they do need to be used with care.

If you care about how your object will be used, use mocks, if you don't, use stubs. Are there mock object frameworks which provide a bit more flexibility; yes, easymock looks quite promising (link).

Will I learn, and start using stubs, probably not :)


- No comments Not publicly viewable


Add a comment

You are not allowed to comment on this entry as it has restricted commenting permissions.

October 2005

Mo Tu We Th Fr Sa Su
Sep |  Today  | Nov
               1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31                  

Search this blog

Tags

Galleries

Most recent comments

  • Interesting… While I'm not completely convinced in such microbenchmarks, I'm pretty sure that 1ms … by Alexander Snaps on this entry
  • Hello. I bought the book yesterday. I was trying to find the source code for chapter 11 and chapter … by Suleman on this entry
  • http://woosight.net/account/login?username=demo by live mashup demo on this entry
  • Thanks mate ….. This blog was really helpful. by Maaz Hurzuk on this entry
  • Ty. Not directly helpful for my problem, but pointed me in the right direction. You will also get th… by Mike E. on this entry

Blog archive

Loading…
Not signed in
Sign in

Powered by BlogBuilder
© MMXXII