开始使用Mockito -- 使用Mockito和JUnit【一】_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 开始使用Mockito -- 使用Mockito和JUnit【一】

开始使用Mockito -- 使用Mockito和JUnit【一】

 2012/1/31 9:22:36  jilen  程序员俱乐部  我要评论(0)
  • 摘要:一段常见的代码单元测试是项目的重要组成部分。尤其是对持续发展的产品,单元测试在后期的维护,回归有重要等方面有重要作用。这样代码在项目中随处可见,看看我们应该如何测试publicclassNotifyService{privateUserCenteruc;privateMessageCentermc;publicvoidsendMessage(longuserId,Stringmessage){Stringemail=uc.getUser(userId).getEmail();mc
  • 标签:使用

一段常见的代码?

单元测试是项目的重要组成部分。尤其是对持续发展的产品,单元测试在后期的维护,回归有重要等方面有重要作用。

? 这样代码在项目中随处可见,看看我们应该如何测试

?

?

public class NotifyService {
	private UserCenter uc;
	private MessageCenter mc;

	public void sendMessage(long userId, String message) {
		String email = uc.getUser(userId).getEmail();
		mc.sendEmail(email, message);
	}

	public void setUc(UserCenter uc) {
		this.uc = uc;
	}

	public void setMc(MessageCenter mc) {
		this.mc = mc;
	}
}

UserCenter和MessageCenter都是接口,User是一个简单的JavaBean

?

由于uc和mc乃外部依赖,此类不需也不应保证uc和mc的正确性,此类只需保证:

? 假设uc和mc是正确的,那么我也是正确的。

所以需要隔离依赖--使用mock

?

使用EasyMock

如果使用EasyMock,此类之单元测试或许如下

?

?

public class EasyMockNotifyServiceTest {
	private NotifyService notifyService;
	private UserCenter uc;
	private MessageCenter mc;

	@Before
	public void setUp() {
		notifyService = new NotifyService();
		uc = createMock(UserCenter.class);
		mc = createMock(MessageCenter.class);
		notifyService.setUc(uc);
		notifyService.setMc(mc);
	}

	@Test
	public void testSendMessage() {
		Long id = 1L;
		String email = "foo@bar";
		String message = "hello";
		expect(uc.getUser(id)).andReturn(createUserWithEmail(email));
		mc.sendEmail(eq(email), eq(message));
		replay(uc);
		replay(mc);
		notifyService.sendMessage(id, message);
		verify(mc);//verify a mocked behavior
	}

	private User createUserWithEmail(String email) {
		User user = new User();
		user.setEmail(email);
		return user;
	}
}
?

?

? ?当然,此测试并不充分,easymock需要mock每个依赖,对mock的所有方法调用作expect,然后验证需要验证的行为。

?

?

?

mc.sendEmail(eq(email), eq(message));

?

? ? 此处代码理解起来有些怪异,实际上,此处的语义应该是 expect mc.sendEmail... called,即方法执行完毕后sendMail必以正确的参数调用,奈何java 泛型中并未覆盖void型,所以通常会在mock行为调用之后

加上此行以明确语义

expectLastCall().times(1);

?

? ? 另外一个值得注意的地方

?

verify(mc);//verify a mocked behavior

?

? ? 并未验证uc,我的想法是对于uc我们需要它提供数据(桩),而不需要验证其行为。

?

? ? 使用Mockito

? ? 假使使用Mockito,单元测试也许是这个样子的

?

public class NotifyServiceTest {
	private NotifyService notifyService;
	private UserCenter uc;
	private MessageCenter mc;

	@Before
	public void setUp() {
		notifyService = new NotifyService();
		uc = mock(UserCenter.class);
		mc = mock(MessageCenter.class);
		notifyService.setUc(uc);
		notifyService.setMc(mc);
	}

	@Test
	public void testSendMessage() {
		long userId = 1L;
		String email = "foo@bar";
		when(uc.getUser(userId)).thenReturn(createUserWithEmail(email));
		notifyService.sendMessage(userId, "hello");
		verify(mc).sendEmail(eq(email), eq("hello"));
	}

	private User createUserWithEmail(String email) {
		User user = new User();
		user.setEmail(email);
		return user;
	}

}
?

看到testSendMessage方法

?

@Test
	public void testSendMessage() {
		long userId = 1L;
		String email = "foo@bar";
		when(uc.getUser(userId)).thenReturn(createUserWithEmail(email));
		notifyService.sendMessage(userId, "hello");
		verify(mc).sendEmail(eq(email), eq("hello"));
	}

?

?

语义不言自明

测试前,从uc获得email

测试后,必须调用mc.sendEmail,所以验证之

?

小结

通过一个简单的例子,可以看到:mockito在使我们代码看直接,语义更明确

?

?

发表评论
用户名: 匿名