过去,很多人问我是否测试吸气剂和吸气剂(属性,属性等)。 他们还问我是否测试我的建筑商。 在我看来,答案取决于情况。

当使用遗留代码时,我不会费心去测试数据结构,这意味着对象只带有getter和setter,映射,列表等。原因之一是我从不模拟它们。 在测试使用它们的类时,我照原样使用它们。 对于构建器,当它们仅由测试类使用时,我也不对它们进行单元测试,因为它们在许多其他测试中均被用作“帮助者”。 如果它们有错误,则测试将失败。 总而言之,如果这些数据结构和构建器已经存在,我不会为它们进行改装测试。

但是,现在让我们谈谈进行TDD并假设您需要一个带有getter和setter的新对象。 在这种情况下,是的,我将为吸气剂和吸气剂编写测试,因为我需要先编写测试来证明它们的存在。
为了拥有丰富的领域模型,我通常倾向于将业务逻辑与数据相关联,并拥有更丰富的领域模型。 让我们看下面的例子。

在现实生活中,我会一次编写测试,使它们通过并重构。 在这篇文章中,为清晰起见,我仅向您提供完整的课程。 首先让我们编写测试:

package org.craftedsw.testingbuilders;import static org.hamcrest.Matchers.is;import static org.junit.Assert.assertThat;import static org.mockito.Matchers.anyString;import static org.mockito.Mockito.verify;import static org.mockito.Mockito.when;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.Mock;import org.mockito.runners.MockitoJUnitRunner;@RunWith(MockitoJUnitRunner.class)public class TradeTest {private static final String INBOUND_XML_MESSAGE = '<message >';private static final boolean REPORTABILITY_RESULT = true;private Trade trade;@Mock private ReportabilityDecision reportabilityDecision;@Beforepublic void initialise() {trade = new Trade();when(reportabilityDecision.isReportable(anyString())).thenReturn(REPORTABILITY_RESULT);}@Test public voidshould_contain_the_inbound_xml_message() {trade.setInboundMessage(INBOUND_XML_MESSAGE);assertThat(trade.getInboundMessage(), is(INBOUND_XML_MESSAGE));}@Test public voidshould_tell_if_it_is_reportable() {trade.setInboundMessage(INBOUND_XML_MESSAGE);trade.setReportabilityDecision(reportabilityDecision);boolean reportable = trade.isReportable();verify(reportabilityDecision).isReportable(INBOUND_XML_MESSAGE);assertThat(reportable, is(REPORTABILITY_RESULT));}}

现在执行:

package org.craftedsw.testingbuilders;public class Trade {private String inboundMessage;private ReportabilityDecision reportabilityDecision;public String getInboundMessage() {return this.inboundMessage;}public void setInboundMessage(String inboundXmlMessage) {this.inboundMessage = inboundXmlMessage;}public boolean isReportable() {return reportabilityDecision.isReportable(inboundMessage);}public void setReportabilityDecision(ReportabilityDecision reportabilityDecision) {this.reportabilityDecision = reportabilityDecision;}}

这种情况很有趣,因为Trade对象具有一个名为inboundMessage的属性,具有相应的getter和setter,并且在其isReportable业务方法中还使用了一个协作者(reportabilityDecision,通过setter注入)。

我多次看到的“测试” setReportabilityDecision方法的常用方法是引入getReportabilityDecision方法,该方法返回reportabilityDecision(协作者)对象。

这绝对是错误的方法。 我们的目标应该是测试协作器的使用方式,这意味着是否使用正确的参数调用了协作器,以及是否使用了返回的任何内容(如果返回了任何内容)。 在这种情况下引入吸气剂是没有意义的,因为它不能保证在通过设置器注入了协作者之后,对象将按照我们的预期与协作者进行交互。

顺便说一句,当我们编写有关如何使用协作者的测试时,定义它们的接口是在将TDD用作设计工具而不仅仅是将其用作测试工具时。 我将在以后的博客文章中介绍。

好的,现在假设可以以不同的方式(即具有不同的可报告性决策)创建此贸易对象。 我们还希望使代码更具可读性,因此我们决定为Trade对象编写一个生成器。 在这种情况下,我们还假设我们希望生成器也用于生产和测试代码中。 在这种情况下,我们要测试驱动器。

这是我通常在开发人员测试驱动构建器实现时发现的一个示例。

package org.craftedsw.testingbuilders;import static org.craftedsw.testingbuilders.TradeBuilder.aTrade;import static org.hamcrest.Matchers.is;import static org.junit.Assert.assertThat;import static org.mockito.Mockito.verify;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.Mock;import org.mockito.runners.MockitoJUnitRunner;@RunWith(MockitoJUnitRunner.class)public class TradeBuilderTest {private static final String TRADE_XML_MESSAGE = '<message >';@Mockprivate ReportabilityDecision reportabilityDecision;@Test public voidshould_create_a_trade_with_inbound_message() {Trade trade = aTrade().withInboundMessage(TRADE_XML_MESSAGE).build();assertThat(trade.getInboundMessage(), is(TRADE_XML_MESSAGE));}@Test public voidshould_create_a_trade_with_a_reportability_decision() {Trade trade = aTrade().withInboundMessage(TRADE_XML_MESSAGE).withReportabilityDecision(reportabilityDecision).build();trade.isReportable();verify(reportabilityDecision).isReportable(TRADE_XML_MESSAGE);}}

现在让我们看看这些测试。 好消息是,这些测试是以开发人员想要阅读它们的方式编写的。 这也意味着他们正在“设计” TradeBuilder公共接口(公共方法)。 坏消息是他们如何对其进行测试。

如果仔细看,构建器的测试几乎与TradeTest类中的测试相同。
您可能会说没问题,因为构建器正在创建对象,并且测试应该相似。 唯一的不同是,在TradeTest中我们手动实例化对象,在TradeBuilderTest中我们使用构建器实例化对象,但是断言应该相同,对吗? 对于我来说,首先我们要重复。 其次,TradeBuilderTest没有显示出它的真实意图。 经过多次重构和探索不同的想法之后,在与团队中的一个人进行配对编程时,我们想到了这种方法:

package org.craftedsw.testingbuilders;import static org.mockito.BDDMockito.given;import static org.mockito.Mockito.verify;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.InjectMocks;import org.mockito.Mock;import org.mockito.Spy;import org.mockito.runners.MockitoJUnitRunner;@RunWith(MockitoJUnitRunner.class)public class TradeBuilderTest {private static final String TRADE_XML_MESSAGE = '<message >';@Mock private ReportabilityDecision reportabilityDecision;@Mock private Trade trade;@Spy @InjectMocks TradeBuilder tradeBuilder;@Test public voidshould_create_a_trade_with_all_specified_attributes() {given(tradeBuilder.createTrade()).willReturn(trade);tradeBuilder.withInboundMessage(TRADE_XML_MESSAGE).withReportabilityDecision(reportabilityDecision).build();verify(trade).setInboundMessage(TRADE_XML_MESSAGE);verify(trade).setReportabilityDecision(reportabilityDecision);}}

因此,现在,TradeBuilderTest表达了TradeBuilder的期望,即调用build方法时的副作用。 我们希望它创建交易并设置其属性。 TradeTest没有重复项。 它留给TradeTest来保证Trade对象的正确行为。
为了完整起见,这是最后的TradeBuider类:

package org.craftedsw.testingbuilders;public class TradeBuilder {private String inboundMessage;private ReportabilityDecision reportabilityDecision;public static TradeBuilder aTrade() {return new TradeBuilder();}public TradeBuilder withInboundMessage(String inboundMessage) {this.inboundMessage = inboundMessage;return this;}public TradeBuilder withReportabilityDecision(ReportabilityDecision reportabilityDecision) {this.reportabilityDecision = reportabilityDecision;return this;}public Trade build() {Trade trade = createTrade();trade.setInboundMessage(inboundMessage);trade.setReportabilityDecision(reportabilityDecision);return trade;}Trade createTrade() {return new Trade();}}

Mockito和Hamcrest的组合功能非常强大,使我们能够编写更好,更易读的测试。

参考:来自Crafts Software博客的JCG合作伙伴 Sandro Mancuso的Mockito和Hamcrest的测试驱动构建器 。

翻译自: https://www.javacodegeeks.com/2012/06/test-driving-builders-with-mockito-and.html

Mockito和Hamcrest的试驾制造商相关推荐

  1. mockito_Mockito和Hamcrest的试驾制造商

    mockito 过去,很多人问我是否测试吸气剂和吸气剂(属性,属性等). 他们还问我是否测试我的建筑商. 在我看来,答案取决于情况. 当使用遗留代码时,我不会费心去测试数据结构,这意味着对象只带有ge ...

  2. maven mockito_如何:测试Maven项目(JUnit,Mockito,Hamcrest,AssertJ)中的依赖项

    maven mockito 对于当今的大多数Java项目而言,JUnit本身还远远不够. 您还需要一个模拟库,也许还有其他东西. 在此迷你操作指南中,我介绍了可以在新的Java项目中开始的测试依赖项. ...

  3. 如何:在Maven项目(JUnit,Mockito,Hamcrest,AssertJ)中测试依赖项

    对于当今的大多数Java项目,JUnit本身还远远不够. 您还需要一个模拟库,也许还有其他东西. 在此迷你操作指南中,我介绍了可以在新的Java项目中开始的测试依赖项. 一切都始于JUnit Mave ...

  4. 微服务架构下的测试之道

    作者:袁慎建,崇尚简约,热爱编程 && 运动健身 && 知识分享,擅长敏捷开发实践,持续集成 && 持续交付,关注代码整洁 && TDD ...

  5. spring boot简介_Spring Boot简介

    spring boot简介 在本教程中,我们将看一下Spring Boot,看看它与Spring框架有何不同. 我们还将讨论Spring Boot提供的各种功能. 什么是Spring Boot? 在开 ...

  6. 使用Spring Data MongoDB和Spring Boot进行数据聚合

    MongoDB聚合框架旨在对文档进行分组并将其转换为聚合结果. 聚合查询包括定义将在管道中执行的几个阶段. 如果您对有关该框架的更深入的细节感兴趣,那么 mongodb docs是一个很好的起点. 这 ...

  7. java静态导入_Java中越来越多地接受静态导入吗?

    java静态导入 曾经有一段时间,至少在礼貌的社会中,人们普遍认为使用" 不是 "一词是不可接受的. 确实,在那个时候(也许直到今天),很多人确实(也确实)不认为这不是一个真实的词 ...

  8. Java是否越来越接受静态导入?

    曾经有一段时间,至少在礼貌的社会中,人们普遍认为使用" 不是 "一词是不可接受的. 确实,那时(也许直到今天),许多人确实(也确实)认为不是一个真实的词. 尽管这个词并没有 引起争 ...

  9. 【Android进阶】20、音频播放:SoundPool 类、单元测试:Espresso框架

    文章目录 20.1 创建 SoundPool 20.2 访问 assets 20.3 加载音频文件 20.4 播放音频 20.5 单元测试 20.6 创建测试类 20.7 配置测试类 20.8 编写测 ...

最新文章

  1. React接入Sentry.js
  2. 【Python】垃圾分类,调用阿里云API
  3. 服务器运行环境怎么搭建,服务器运行环境怎么快速搭建?
  4. HDU 5938 Four Operations 【字符串处理,枚举,把数字字符串变为数值】
  5. LI标签在Ul中居中显示
  6. 剑指offer(15)反转链表
  7. leetcode349. 两个数组的交集(思路+详解)
  8. P2568-GCD【欧拉函数,欧拉筛】
  9. 工作流实战_07_flowable 流程定义查看流程图和xml
  10. Java双端队列Deque及其应用
  11. 注入器 过检测_福特全顺V348检测车报价
  12. 练习:----计算阶乘按钮
  13. 练习|Django-单表
  14. 2020张宇1000题【好题收集】【第七章:三重积分、曲线曲面积分】
  15. mysql 批量 插入或更新
  16. Jquery中fadein() fadeout()方法的使用
  17. 盘点“大宗商品电子交易模式”的8种交易流程
  18. 跨模态检索 | Visual Representation Learning
  19. Qwerty Learner:为键盘工作者设计的单词记忆与英语肌肉记忆锻炼网页
  20. ehvierwer登录与不登录_微信号提示“系统检测有被盗风险”登录不上去该如何解决?...

热门文章

  1. Java虚拟机详解----常用JVM配置参数
  2. java流与文件——操作文件
  3. Java8 Lambda总结
  4. 成为Java流专家–第2部分:中级操作
  5. Java,JavaFX的流利设计风格文本字段和密码字段
  6. 使用Java流查询数据库
  7. Java命令行界面(第17部分):jw-options
  8. 通过分区在Kafka中实现订单保证人
  9. 小规模流处理kata。 第1部分:线程池
  10. stringutils_番石榴分配器vs StringUtils