5/11/2007
Why Do We Need Mock Framework?
Given we have a simple behavior to test:
a form
a text field on the form
a button on the form
click the button, should set the text of the text field to "Hello"
And, here is the code implementing the behavior, MVP pattern is applied here:
public interface View { public void setText(String text); public void addActionListener(ActionListener actionListener); }
public class Presenter { public Presenter(final View view) { view.addActionListener(new ActionListener() { public void actionPerformed() { view.setText("Hello"); } }); } }Before writing the test in java, let's first write in pseudo-code:
create mock view create presenter by mock view fire event on mock view assert text is setThen, let's implement it using latest jMock:
@Test public void test_click_button_should_set_text_hello() { Mockery mockery = new Mockery(); final View mockView = mockery.mock(View.class); final ActionListenerMatcher actionListenerMatcher = new ActionListenerMatcher(); mockery.checking(new Expectations() { { one(mockView).addActionListener(with(actionListenerMatcher)); one(mockView).setText("Hello"); } }); new Presenter(mockView); actionListenerMatcher.fireActionPerformed(); mockery.assertIsSatisfied(); }Here, we introduced a custom matcher, called ActionListenerMatcher. The reason why we need this, is because we need a way to fire the event. Without the matcher, we have no place to store the listener passed in. Here is the implementation of ActionListenerMatcher:
public class ActionListenerMatcher extends BaseMatcherWhat is the conclusion? The intention of developer when writing the test is lost in the long and complex mocking code. How about other frameworks? I have tried EasyMock as well, which is even worse than jMock. Do we have a simpler way? Yes, we have. Check this out:{ private ActionListener actionListener; public boolean matches(Object item) { actionListener = (ActionListener) item; return true; } public void fireActionPerformed() { actionListener.actionPerformed(); } public void describeTo(Description description) { } }
@Test public void test_click_button_should_set_text_hello() { MockView mockView = new MockView(); new Presenter(mockView); mockView.fireActionPerformed(); Assert.assertEquals("Hello", mockView.getText()); }Isn't this simple? MockView is just a simple implementation of View:
private class MockView implements View { private ActionListener actionListener; private String text; public void addActionListener(ActionListener actionListener) { this.actionListener = actionListener; } public void setText(String text) { this.text = text; } public String getText() { return text; } public void fireActionPerformed() { actionListener.actionPerformed(); } }So, before you starting to use a mock framework. Think about it, do we really need them?
Subscribe to Posts [Atom]