mock框架搞什么搞?

今天早上一时兴起,去网上下载下来JMock,EasyMock最新版本来玩玩。用来测试的行为很简单。就是有一个窗体,上面有一个文本框,一个按钮。如果点击按钮,就会把文本框的内容设置为“Hello”。应用MVP模式,这个行为应该在Presenter中,而View接口应该是这样的:

public interface View {
	public void setText(String text);
	public void addActionListener(ActionListener actionListener);
}


我这里就不TDD了,直接给出Presenter的实现,然后我们来看JMock和EasyMock如何处理这个问题。

public class Presenter {
	public Presenter(final View view) {
		view.addActionListener(new ActionListener() {
			public void actionPerformed() {
				view.setText("Hello");
			}
		});
	}
}


好的,我先来写一段伪测试代码:

引用

创建MockView
创建Presenter,传以MockView做为参数
在MockView上触发事件
验证MockView的SetText方法被调用了


然后就用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();
	}


由于JMock没有对触发事件提供直接的支持,所以是自己写了一个ActionListenerMatcher来达到这个目的的。这个Matcher的实现如下:

public class ActionListenerMatcher extends BaseMatcher<ActionListener> {

	private ActionListener actionListener;

	public boolean matches(Object item) {
		actionListener = (ActionListener) item;
		return true;
	}

	public void fireActionPerformed() {
		actionListener.actionPerformed();
	}

	public void describeTo(Description description) {
	}

}


可以看到之所以要这个Matcher是因为,我们需要有一个地方来保存Presenter传进来的listener,并且提供一个用来触发事件的方法。

EasyMock的实现与之非常类似,此处不再赘述。代码可以参见附件。

我们可以看到什么?我看到的是,测试时候的Intention(意图)完全掩盖在冗长复杂的代码之中了。如果不用Mock该怎么做?很简单:

@Test
public void test_click_button_should_set_text_hello() {
		MockView mockView = new MockView();
		new Presenter(mockView);
		mockView.fireActionPerformed();
		Assert.assertEquals("Hello", mockView.getText());
	}


这段代码是不是和上面的伪代码一模一样?MockView是这样的:

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();
		}
	}


做完这个实验,我不得不说。Mock框架,搞什么搞!简单一点不好么?

猜你喜欢

转载自taowen.iteye.com/blog/78824