一段常见的代码
单元测试是项目的重要组成部分。尤其是对持续发展的产品,单元测试在后期的维护,回归有重要等方面有重要作用。
这样代码在项目中随处可见,看看我们应该如何测试
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,此类之单元测试或许如下[需要static import org.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,单元测试也许是这个样子的[需要static import org.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在使我们的测试代码更直接,语义更明确
分享到:
相关推荐
mockito-all-1.10.19.jar mockito-core-4.5.1.jar mockito-junit-jupiter-4.5.1.jar mockito-junit-jupiter-4.5.1-sources.jar
mockito-junit-jupiter-3.3.3.jarmockito-junit-jupiter-3.3.3.jar
mockito-junit-jupiter-3.6.0.jarmockito-junit-jupiter-3.6.0.jar
java运行依赖jar包
powermock-mockito-junit-1.6.3.zip 当前最新版,请使用1.6以上版本jdk。 如果抛出 Bad version in .class file,请检查jdk版本是否太低
PowerMock+Mockito-junit测试套件1.6.3版本
mockito junit 单元测试 mockito junit 单元测试
·本文档为双语同时展示,一行原文、一行译文,可逐行对照,避免了原文/译文来回切换的麻烦; ·有原文可参照,不再担心翻译偏差误导; ·边学技术、边学英语。 ·只翻译了该翻译的内容,如:注释、说明、描述、...
使用 mockito-core 而不是 mockito-all 的 PowerMock 示例。 问题(参见 pom.xml): a) 如果 JUnit 在 powermock-api-mockito 之前是显式依赖项,则 JUnit 的 Hamcrest 1.3 依赖项会获胜并且测试运行良好。 b) ...
·本文档为双语同时展示,一行原文、一行译文,可逐行对照,避免了原文/译文来回切换的麻烦; ·有原文可参照,不再担心翻译偏差误导; ·边学技术、边学英语。 ·只翻译了该翻译的内容,如:注释、说明、描述、...
junit单元测试所需架包及依赖集成版(包含hamcrest-all-1.3.jar、junit-4.12.jar、mockito-all-1.10.19.jar),引入项目即可直接使用,不依赖网络 使用教程及自动化测试示例 请看...
powermock 版本要求比较严格,请使用1.6及以上jdk
Java-Junit-Mockito 课程概述步骤列表JUnit步骤01:需要单元测试步骤02:设置您的第一个JUnit步骤03:第一个成功的JUnit。 Green Bar和assertEquals步骤04:重构您的第一个JUnit测试步骤05:第二个JUnit示例...
它间接引用 junit-4.12 mockito-core-2.15.0 但是官网powermock 1.7.x只支持2.8.0-2.8.9,如果使用默认引入版本,会出现找不到某些方法的异常. 需要自定义mockito-core为相应版本。 ServiceAspect只是为了验证当spy...
java运行依赖jar包
官方版本,亲测可用
·本文档为双语同时展示,一行原文、一行译文,可逐行对照,避免了原文/译文来回切换的麻烦; ·有原文可参照,不再担心翻译偏差误导; ·边学技术、边学英语。 ·只翻译了该翻译的内容,如:注释、说明、描述、...
·本文档为双语同时展示,一行原文、一行译文,可逐行对照,避免了原文/译文来回切换的麻烦; ·有原文可参照,不再担心翻译偏差误导; ·边学技术、边学英语。 ·只翻译了该翻译的内容,如:注释、说明、描述、...
·本文档为双语同时展示,一行原文、一行译文,可逐行对照,避免了原文/译文来回切换的麻烦; ·有原文可参照,不再担心翻译偏差误导; ·边学技术、边学英语。 ·只翻译了该翻译的内容,如:注释、说明、描述、...
SOAP Web服务模拟实用程序,使用Web服务器实例在本地端口上创建真实的服务端点。 这些端点将请求直接委托给模拟。 用户将从中受益 全栈客户端测试 拦截器 处理程序 简单的JUnit规则设置 SOAP故障帮手 所有这些都...