我的上一个博客是有关测试代码的方法以及讨论您要做和不需要进行测试的方法的一系列博客中的第三篇。 它基于我使用一种非常常见的模式从数据库中检索地址的简单方案:

…并且我提出了这样的想法:任何不包含任何逻辑的类都不需要进行单元测试。 在其中,我包括了我的数据访问对象DAO,而不是对此类进行集成测试以确保其与数据库协同工作。

今天的博客涵盖编写常规或经典的单元测试,该测试使用存根对象强制实现测试主题隔离。 我们将要测试的代码再次是AddressService

@Component
public class AddressService {private static final Logger logger = LoggerFactory.getLogger(AddressService.class);private AddressDao addressDao;/*** Given an id, retrieve an address. Apply phony business rules.* * @param id*            The id of the address object.*/public Address findAddress(int id) {logger.info("In Address Service with id: " + id);Address address = addressDao.findAddress(id);address = businessMethod(address);logger.info("Leaving Address Service with id: " + id);return address;}private Address businessMethod(Address address) {logger.info("in business method");// Apply the Special Case Pattern (See MartinFowler.com)if (isNull(address)) {address = Address.INVALID_ADDRESS;}// Do some jiggery-pokery here....return address;}private boolean isNull(Object obj) {return obj == null;}@Autowired@Qualifier("addressDao")void setAddressDao(AddressDao addressDao) {this.addressDao = addressDao;}
}

迈克尔·费瑟(Michael Feather)的书《有效使用旧版代码》指出,在以下情况下,测试不是单元测试:

  1. 它与数据库对话。
  2. 它通过网络进行通信。
  3. 它涉及文件系统。
  4. 您必须对环境做一些特殊的事情(例如编辑配置文件)才能运行它。

为了遵守这些规则,您需要将测试对象与系统的其余部分隔离开来,这就是存根对象的所在。存根对象是注入到您的对象中的对象,用于在测试情况下替换实际对象。 马丁·福勒(Martin Fowler)在他的论文《 莫克斯不是存根》中将存根定义为:

“存根提供对测试过程中进行的呼叫的固定答复,通常通常根本不响应测试中编程的内容。 存根还可以记录有关呼叫的信息,例如电子邮件网关存根,它可以记住“已发送”的消息,或者仅记住“已发送”的消息数量。”

用一个单词来描述存根非常困难,我可以选择虚拟或伪造,但是有些替换对象称为假人或伪造-也由Martin Fowler描述:

  • 虚拟对象会传递,但从未实际使用过。 通常它们仅用于填充参数列表。
  • 伪对象实际上具有有效的实现,但是通常采取一些捷径,这使它们不适合生产(内存数据库是一个很好的例子)。

但是,我看到过其他术语“伪造对象”的定义,例如Roy Osherove在《 The Art Of Unit Testing》一书中将伪造对象定义为:

  • 伪造品是一个通用术语,可用于描述存根或模拟对象……因为两者看起来都像真实对象。

…因此,我和其他许多人一样,倾向于将所有替换对象称为模拟或存根,因为两者之间存在差异,但稍后会更多。

在测试AddressService时 ,我们需要用存根数据访问对象替换实际的数据访问对象,在这种情况下,它看起来像这样:

public class StubAddressDao implements AddressDao {private final Address address;public StubAddressDao(Address address) {this.address = address;}/*** @see com.captaindebug.address.AddressDao#findAddress(int)*/@Overridepublic Address findAddress(int id) {return address;}
}

注意存根代码的简单性。 它应该易于阅读,可维护,并且不包含任何逻辑,并且需要自己进行单元测试。 编写存根代码后,接下来进行单元测试:

public class ClassicAddressServiceWithStubTest {private AddressService instance;@Beforepublic void setUp() throws Exception {/* Create the object to test *//* Setup data that's used by ALL tests in this class */instance = new AddressService();}/*** Test method for* {@link com.captaindebug.address.AddressService#findAddress(int)}.*/@Testpublic void testFindAddressWithStub() {/* Setup the test data - stuff that's specific to this test */Address expectedAddress = new Address(1, "15 My Street", "My Town","POSTCODE", "My Country");instance.setAddressDao(new StubAddressDao(expectedAddress));/* Run the test */Address result = instance.findAddress(1);/* Assert the results */assertEquals(expectedAddress.getId(), result.getId());assertEquals(expectedAddress.getStreet(), result.getStreet());assertEquals(expectedAddress.getTown(), result.getTown());assertEquals(expectedAddress.getPostCode(), result.getPostCode());assertEquals(expectedAddress.getCountry(), result.getCountry());}@Afterpublic void tearDown() {/** Clear up to ensure all tests in the class are isolated from each* other.*/}
}

请注意,在编写单元测试时,我们的目标是清晰。 通常会犯一个错误,就是认为测试代码不如生产代码,从而导致测试代码更加混乱且难以辨认。 单元测试的艺术中的 Roy Osherove提出了这样的想法,即测试代码应比生产代码更具可读性。 明确的测试应遵循以下基本的线性步骤:

  1. 创建被测对象。 在上面的代码中,这是在setUp()方法中完成的,因为我正在对所有(一个)测试使用相同的被测对象。
  2. 设置测试。 这是在测试方法testFindAddressWithStub()中完成的,因为测试中使用的数据特定于该测试。
  3. 运行测试
  4. 撕毁测试。 这样可以确保测试彼此隔离,并且可以按任何顺序运行。

使用简单的存根会产生将AddressService与外界隔离和快速运行测试的两个好处。

这种测试有多脆? 如果您的要求改变了,那么测试和存根就会改变–毕竟不是那么脆弱吗?

作为比较,我的下一个博客使用EasyMock重写了该测试。

参考: 定期的单元测试和存根-来自JCG合作伙伴 Roger Hughes的Captain Debug博客上的 测试技术4

相关文章 :

  • 测试技巧–不编写测试
  • 端到端测试的滥用–测试技术2
  • 您应该对什么进行单元测试? –测试技术3
  • 使用模拟的单元测试–测试技术5
  • 为旧版代码创建存根–测试技术6
  • 有关为旧版代码创建存根的更多信息–测试技术7
  • 为什么要编写单元测试–测试技巧8
  • 一些定义–测试技术9
  • 使用FindBugs产生更少的错误代码
  • 在云中开发和测试

翻译自: https://www.javacodegeeks.com/2011/11/regular-unit-tests-and-stubs-testing.html

常规单元测试和存根–测​​试技术4相关推荐

  1. 存根类 测试代码 java_常规单元测试和存根–测​​试技术4

    存根类 测试代码 java 我的上一个博客是有关测试代码的方法以及讨论您做什么和不必进行测试的方法的一系列博客中的第三篇. 它基于我使用一种非常常见的模式从数据库检索地址的简单方案: -并且我提出了这 ...

  2. 百度单测生成技术如何召回线上服务的异常问题?

    导读:线上系统异常问题一直以来都是使人"闻风丧胆"的,传统手段在解决这类问题时面临着相应的技术瓶颈.基于此,探索基于单元测试召回异常问题的方法,实现了一套通用且无人参与的单测生成系 ...

  3. 测 试 基 础 知 识

    测 试 基 础 1.     软件测试的目的:证明(表达软件能够工作)→ 检测(发现错误)→ 预防(管 理质量) 2.    测试执行:单元测试(UT执行):一个测试用例的测试执行: 集成测试(IT执 ...

  4. 写好测试,提升应用质量。涨薪分分钟!!!(二)之单元测试下开发模式、技术框架选择

    目录: 四. 单元测试下开发模式.技术框架选择 单元测试是按照测试范围来划分的.TDD.BDD 是按照开发模式来划分的.因此就有各种排列组合,这里我们只关心单元测试下的 TDD.BDD 方案. 在单元 ...

  5. 中国石油大学计算机测控技术在线考试,2020年中国石油大学网络教育040129计算机测控技术-20考试试题及参考答案.pdf...

    <计算机测控技术>综合复习资料 一.填空题 1.过程通道包括: __________ .____________ .______________ .____________ . 2.若连续 ...

  6. 虹科案例 | 光热测厚技术助力PSA无底漆涂装方案

    法国标致雪铁龙集团(PSA Peugeot Citroën)最开始是生产胡椒研磨机,然后将其产品组合扩展到自行车等,现在已经是欧洲第二大汽车制造商.巴黎郊外的普瓦西(Poissy) 工厂安装了法国首个 ...

  7. 移动測试技术保护源码!解码全球首款移动端白盒測试工具ThreadingTest (文章转自己主动点科技)...

    作者 智晓锋 - 2014/07/14 自从斯诺登曝光美监听丑闻事件之后,我国政府就将信息安全问题上升到了国家安全的高度.基于此.国内的一家创业公司推出了智能型Android真机白盒測试以及开发辅助类 ...

  8. 测控技术与仪器专业c语言教学视频,测控技术与仪器要学哪些基础和专业课程...

    育路高校招生网为您整理了"测控技术与仪器专业要学习的基础和专业课程",方便广大网友查阅!更多相关信息请访问育路高校招生网. 测控技术与仪器专业要学习的基础和专业课程: 1.基础课有 ...

  9. 测控技术与仪器是计算机相关的,测控技术与仪器专业

    欢迎大家来到unjs网,以下是小编为大家用心搜集整理的测控技术与仪器专业相关内容,我们一起来看看吧! [测控技术与仪器专业介绍] 测控技术与仪器专业是信息科学技术的源头,是光学.精密机械.电子.电力. ...

最新文章

  1. 运行时权限框架YPermission开源
  2. BBED修复DB启动问题
  3. ubuntu下安装gedit插件
  4. HDU 2009 求数列的和
  5. j2ee gradle构建
  6. python中控制台输出的颜色方法
  7. 三合一剪弦器怎么用_三合一冲锋衣推荐选购攻略:
  8. android插件化-获取apkplug框架已安装插件-03
  9. BugkuCTF-WEB题GET和POST
  10. 如何在Xcode 4中“添加现有框架”?
  11. 那些远去的人,那段伟大的历史【ZZ】
  12. YCrCb444转换成YCrCb422随笔
  13. 卷积神经网络第四周作业1 - Face Recognition for the Happy House - v1
  14. [2018.04.29 T1] 图
  15. [转贴]搜索引擎优化(SEO)菜鸟版@搜索引擎研究专案
  16. Wowza服务器系列(4):使用rtmp协议向wowza推流的wowoza配置方法
  17. 【养眼美女win7主题】主题世界
  18. 如何设计一款优秀的短视频 SDK
  19. 程序员最重要的核心竞争力是什么?
  20. word中最后一行留白太多

热门文章

  1. 快慢指针:141. 环形链表(判断是否存在环路)
  2. tdd java_适用于Idea的面向现代TDD的Java 8 JUnit测试模板(带有Mockito和AssertJ)
  3. rxjava 背压_背压加载文件– RxJava常见问题解答
  4. cloud foundry_实际的Reactor操作–检索Cloud Foundry应用程序的详细信息
  5. 那是两个小时我不会回来
  6. 背包问题九讲_背包问题
  7. slf4j 桥接与被桥接_合成和桥接方法
  8. 内存heap_哪个内存更快?Heap或ByteBuffer或Direct?
  9. 使用jstat的JVM统计信息
  10. idea使用junit测试_在JUnit测试中使用Builder模式