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 Comments [Atom]