Monday, January 12, 2009

More about Mocks and Mockito

I've been digging around for more about Mockito and how it's different from EasyMock / jMock here's what I got:

I think there are very few use cases for mocks. They produce brittle tests and are hard to read. In addition 99% of the time you don't want a mock, you want a test spy. So why if you had the choice would you choose a mocking framework over a test spy framework?

MoreUnit Test Method Names

I got a patch accepted to the MoreUnit project. If you pull down Head and build / install the plugin there is a new option which allows you to specify whether you want your methods to be created in the style of "testFoo" or just "foo"

I've been using moreUnit pretty steadily for about 2 weeks and it is a huge productivity enhancer. if you're doing TDD you should definitely install the plugin!

Thursday, January 8, 2009

EasyMock vs Mockito

I've been meaning to write about this for a little bit, but first check out a Jay Fields post Ubiquitous Assertion Syntax. I really like the idea that tests follow a similar structure and I'm okay with the JUnit style.

@Test public void methodFoo_should_do_X_when_Y() { test setup test setup test setup assertEquals(a, b); }
What's important to me is that the assertions always come at the end of the test and it's clear what you are asserting, without needing to rely on the method name. Here's an example:
public class Foo() { private Bar bar; private String something = null; private String somethingElse = null; public Foo(Bar bar) { = bar; } public void setStuffUp() { this.something = bar.a(); this.somethingElse = bar.b(); } public Foo callBarC() { return bar.c(something,somethingElse); } }
How a Mockito test might look:
@Test public void callBarC_reallyBadTestName() { Bar bar = mock(Bar.class); Foo foo = new Foo(bar); when(bar.a()).thenReturn("A"); when(bar.b()).thenReturn("B"); foo.setStuffUp(); foo.callBarC(); verify(bar).c("A","B"); }
How an EasyMock example might look:
@Test public void callBarC_reallyBadTestName() { Bar bar = createMock(Bar.class); Foo foo = new Foo(bar); expect(bar.a()).andReturn("A"); expect(bar.b()).andReturn("B"); expect(bar.c("A","B").andReturn(null); replay(bar); foo.setStuffUp(); foo.callBarC(); verify(bar); }

In the Mockito version it's clear what behavior you are testing... it says verify(bar).c("A","B"); But in the EasyMock version the code itself does tell you what you're testing, you have to rely on the bad test name. You could argue that I'm testing all the expectations, but most often you're not. It's not uncommon to have two mocks one that sets up state for another one, the one you're really interested in testing, the focus of your test. Something like:

@Test public void verifyBar2_is_called_correctly() { Bar1 bar1 = createMock(Bar1.class); Bar2 bar2 = createMock(Bar2.class); Foo foo = new Foo(bar1,bar2);; expect(bar1.a()).andReturn("A"); expect(bar1.b()).andReturn("B"); expect(bar1.c("A","B").andReturn(null); replay(bar1,bar2); foo.setStuffUp(); foo.callBarC(); verify(bar1,bar2); }

In this example except for the test name, it's unclear what the intent of the test is. Here it is in mockito

@Test public void verifyBar2_is_called_correctly() { Bar1 bar1 = mock(Bar1.class); Bar2 bar2 = mock(Bar2.class); Foo foo = new Foo(bar1,bar2); when(bar1.a()).thenReturn("A"); when(bar1.b()).thenReturn("B"); when(bar1.c("A","B").thenReturn(null); foo.setStuffUp(); foo.callBarC(); verify(bar2).foo(); }

In mockito, even if I put in a bad test name, the syntax of the test preserves the intent. This is really important. Easymock was a great library, but I think as Jay put it Mockito starts to bring us to testing 2.0

The google testing blog just published an article Use EasyMock I guess I just disagree. Mockito grew out of EasyMock, and I think they took a great library and made it even better, so I really think the title of the post should have been "Use Mockito" not EasyMock. Anyway... there's a whole lot more that Mockito does check out the examples and get off the EasyMock and start drinking the Mockito :P

Web Statistics