作者:Andrew Trenk
原文链接:
http://googletesting.blogspot.tw/2013/07/testing-on-toilet-know-your-test-doubles.html
测试替身在测试中用来代替真实的对象,就好比在电影中特技演员替身来代替演员一样。有时各类的测试替身都会被当成“mocks”,但实际上它们的用途是不同的,所以我们有必要学习如何区分各类的测试替身。最常见的测试替身有这几种:stub,mock和fakes。
stub没有考虑逻辑,它只是按要求返回你想要的内容。stub可以在这种情况下使用:为了使在测试状态的代码进入某一特定状态,你需要一个对象来返回特殊值。手工编写stub语句并不难,但使用mocking框架通常可以更轻易实现样板文件的减少。
//传入一个由mocking框架产生的stub.
AccessManager accessManager = newAccessManager(stubAuthenticationService);
// 当身份验证服务返回false的时候,用户是无权限访问的。
when(stubAuthenticationService.isAuthenticated(USER_ID)).thenReturn(false);
assertFalse(accessManager.userHasAccess(USER_ID));
//当身份验证服务返回true的时候,用户是有权限访问的。
when(stubAuthenticationService.isAuthenticated(USER_ID)).thenReturn(true);
assertTrue(accessManager.userHasAccess(USER_ID));
mock包含有期望,若测试结果未实现该期望,那么该测试是失败的。mock通常用来测试对象之间的交互,当你在执行某种测试的过程中看不出它的状态变化也没有可验证的返回值,这时mock就显得特别有用(例如,你的代码要从磁盘中读取,而你想要确保该操作最多只读取磁盘一次,这时你可以通过mock来验证该读取方法只调用了一次)。
//传入一个由mocking框架产生的mock.
AccessManager accessManager = newAccessManager(mockAuthenticationService);
accessManager.userHasAccess(USER_ID);
//如果 accessManager.userHasAccess(USER_ID)没有调用//mockAuthenticationService.isAuthenticated(USER_ID)或者调用超过一次,这个测试就会失败。
verify(mockAuthenticationService).isAuthenticated(USER_ID);
fake不使用mocking框架,它是一个轻量级的接口实现,和真正的实现表现无异,但它不能和产品相匹配(例如内存数据库)。当你不能使用真实的实现进行测试时,你可以使用fake来代替(比如真实工具运行过慢或需要联网)。你不需要经常编写fake因为fake通常由真正实现的所有者进行创建和维护。
//创建fake是很快速和容易的。
AuthenticationService fakeAuthenticationService = newFakeAuthenticationService();
AccessManager accessManager = newAccessManager(fakeAuthenticationService);
//当身份验证服务并不知道该用户时,用户是无权限访问的assertFalse(accessManager.userHasAccess(USER_ID));
// 当用户已经被添加到身份验证服务中,该用户是有权限访问的。
fakeAuthenticationService.addAuthenticatedUser(USER_ID);
assertTrue(accessManager.userHasAccess(USER_ID));