mock测试使用断言_使用自定义断言丰富测试代码

mock测试使用断言

受GeeCON会议期间@tkaczanowski演讲的启发,我决定仔细研究AssertJ库的自定义断言。

在我的“骰子”游戏中,我创建了一个“机会”,它是骰子的任何组合,其分数是所有骰子的总和。 这是相对简单的对象:

class Chance implements Scorable {@Overridepublic Score getScore(Collection<Dice> dice) {int sum = dice.stream().mapToInt(die -> die.getValue()).sum();return scoreBuilder(this).withValue(sum).withCombination(dice).build();}
}public interface Scorable {Score getScore(Collection<Dice> dice);
}

在我的测试中,我想看看如何计算不同骰子组合的分数。 我从简单开始(实际上只有一个):

public class ChanceTest {private Chance chance = new Chance();@Test@Parameterspublic void chance(Collection<Dice> rolled, int scoreValue) {// arrangeCollection<Dice> rolled = dice(1, 1, 3, 3, 3);// actScore score = chance.getScore(rolled);// assertassertThat(actualScore.getScorable()).isNotNull();assertThat(actualScore.getValue()).isEqualTo(expectedScoreValue);assertThat(actualScore.getReminder()).isEmpty();assertThat(actualScore.getCombination()).isEqualTo(rolled);}}

测试中验证了单个概念(得分对象)。 为了提高分数验证的可读性和可重用性,我将创建一个自定义断言。 我希望我的断言像其他任何AssertJ断言一样被使用,如下所示:

public class ChanceTest {private Chance chance = new Chance();@Testpublic void scoreIsSumOfAllDice() {Collection<Dice> rolled = dice(1, 1, 3, 3, 3);Score score = chance.getScore(rolled);ScoreAssertion.assertThat(score).hasValue(11).hasNoReminder().hasCombination(rolled);}
}

为了实现这一点,我需要创建一个从org.assertj.core.api.AbstractAssert扩展的ScoreAssertion类。 该类应具有公共静态工厂方法和所有必需的验证方法。 最后,实现可能如下图所示。

class ScoreAssertion extends AbstractAssert<ScoreAssertion, Score> {protected ScoreAssertion(Score actual) {super(actual, ScoreAssertion.class);}public static ScoreAssertion assertThat(Score actual) {return new ScoreAssertion(actual);}public ScoreAssertion hasEmptyReminder() {isNotNull();if (!actual.getReminder().isEmpty()) {failWithMessage("Reminder is not empty");}return this;}public ScoreAssertion hasValue(int scoreValue) {isNotNull();if (actual.getValue() != scoreValue) {failWithMessage("Expected score to be <%s>, but was <%s>", scoreValue, actual.getValue());}return this;}public ScoreAssertion hasCombination(Collection<Dice> expected) {Assertions.assertThat(actual.getCombination()).containsExactly(expected.toArray(new Dice[0]));return this;}
}

创建这样的断言的动机是拥有更多可读性和可重用性的代码。 但这要付出一些代价–需要创建更多代码。 在我的示例中,我知道我很快就会创建更多Scorables并且需要验证它们的评分算法,因此创建附加代码是合理的。 增益将可见。 例如,我创建了一个NumberInARow类,该类计算给定骰子组合中所有连续数字的分数。 分数是具有给定值的所有骰子的总和:

class NumberInARow implements Scorable {private final int number;public NumberInARow(int number) {this.number = number;}@Overridepublic Score getScore(Collection<Dice> dice) {Collection<Dice> combination = dice.stream().filter(value -> value.getValue() == number).collect(Collectors.toList());int scoreValue = combination.stream().mapToInt(value -> value.getValue()).sum();Collection<Dice> reminder = dice.stream().filter(value -> value.getValue() != number).collect(Collectors.toList());return Score.scoreBuilder(this).withValue(scoreValue).withReminder(reminder).withCombination(combination).build();}
}

我从连续检查两个5的测试开始,但是我已经错过了断言( hasReminder ,因此改进了ScoreAssertion 。 我继续用其他测试更改断言,直到获得可以在测试中使用的非常完善的DSL:

public class NumberInARowTest {@Testpublic void twoFivesInARow() {NumberInARow numberInARow = new NumberInARow(5);Collection<Dice> dice = dice(1, 2, 3, 4, 5, 5);Score score = numberInARow.getScore(dice);// static import ScoreAssertionassertThat(score).hasValue(10).hasCombination(dice(5, 5)).hasReminder(dice(1, 2, 3, 4));}@Testpublic void noNumbersInARow() {NumberInARow numberInARow = new NumberInARow(5);Collection<Dice> dice = dice(1, 2, 3);Score score = numberInARow.getScore(dice);assertThat(score).isZero().hasReminder(dice(1, 2, 3));}
}public class TwoPairsTest {@Testpublic void twoDistinctPairs() {TwoPairs twoPairs = new TwoPairs();Collection<Dice> dice = dice(2, 2, 3, 3, 1, 4);Score score = twoPairs.getScore(dice);assertThat(score).hasValue(10).hasCombination(dice(2, 2, 3, 3)).hasReminder(dice(1, 4));}
}

更改后的断言如下所示:

class ScoreAssertion extends AbstractAssert<ScoreAssertion, Score> {protected ScoreAssertion(Score actual) {super(actual, ScoreAssertion.class);}public static ScoreAssertion assertThat(Score actual) {return new ScoreAssertion(actual);}public ScoreAssertion isZero() {hasValue(Score.ZERO);hasNoCombination();return this;}public ScoreAssertion hasValue(int scoreValue) {isNotNull();if (actual.getValue() != scoreValue) {failWithMessage("Expected score to be <%s>, but was <%s>",scoreValue, actual.getValue());}return this;}public ScoreAssertion hasNoReminder() {isNotNull();if (!actual.getReminder().isEmpty()) {failWithMessage("Reminder is not empty");}return this;}public ScoreAssertion hasReminder(Collection<Dice> expected) {isNotNull();Assertions.assertThat(actual.getReminder()).containsExactly(expected.toArray(new Dice[0]));return this;}private ScoreAssertion hasNoCombination() {isNotNull();if (!actual.getCombination().isEmpty()) {failWithMessage("Combination is not empty");}return this;}public ScoreAssertion hasCombination(Collection<Dice> expected) {isNotNull();Assertions.assertThat(actual.getCombination()).containsExactly(expected.toArray(new Dice[0]));return this;}
}

我真的很喜欢自定义AssertJ断言的想法。 在某些情况下,它们将提高我的代码的可读性。 另一方面,我很确定不能在所有情况下都使用它们。 尤其是在那些可重用机会很小的地方。 在这种情况下,可以使用带有分组断言的私有方法。

你有什么意见?

资源资源

  • https://github.com/joel-costigliola/assertj-core/wiki/Creating-specific-assertions
  • @tkaczanowski的断言演变

翻译自: https://www.javacodegeeks.com/2014/05/spice-up-your-test-code-with-custom-assertions.html

mock测试使用断言

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/341219.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何实现有序列表端内换行

背景 有序列表换行后自动开启下一个标号&#xff0c;让人苦恼。 操作 操作系统换行操作 1. 【Enter】键是硬回车&#xff0c;即段落标记。回车后文字属于下一段落 2. 【shiftEnter】是软回车快捷键。即人工换行符。回车后文字仍属于前一段落&#xff0c;只不过重新换行。 …

Java性能:For-eaching与Streaming

在for循环中向上或向下计数是最有效的迭代方式吗&#xff1f; 有时答案既不是。 阅读这篇文章&#xff0c;了解不同迭代品种的影响。 迭代性能 关于如何以高性能进行迭代有很多观点。 Java中的传统迭代方式是一个for循环&#xff0c;该循环从零开始&#xff0c;然后计数到一些…

好用的截图工具

目录 截图软件介绍 神器2——Snipaste PicPick——自带画图 LightShot——自带图床 功能总结 截图软件介绍 参考推荐5个截图工具&#xff08;超好用&#xff09; - 知乎&#xff0c;列出几个好用的截图工具 神器2——Snipaste 超级好用&#xff0c;QQ的功能Snipaste全都有…

Markdown语法与文本内容冲突的解决方案(软件Typora)

背景 使用Typora输入文字后&#xff0c;其中特殊字符自动识别为Markdown语法 解决方式 在使用markdown书写博客时&#xff0c;有可能会出现文本中的字符是markdown语法&#xff0c;那么markdown翻译器就会误将这些符号也翻译成某种功能&#xff0c;就会出现显示错误的情况。…

如何在Flutter(REST API)中进行API调用

在本文中&#xff0c;我们将探讨如何在波动中进行API调用并使用简单的REST API。 在这里查看我在Flutter上的其他一些帖子&#xff1a; Flutter vs React Native 了解Flutter中的BLoC架构 &#xff08;强烈建议&#xff09; 在Flutter中构建ListView&#xff08;RecyclerVi…

sublime关闭左边文件路径快捷键

目录 背景 解决方法 方案一&#xff1a; 方案二&#xff1a; 背景 sublime查看某一文件具体内容&#xff0c;左边文件路径占用一部分空间&#xff0c;影响观看 解决方法 方案一&#xff1a; 使用快捷键&#xff1a;关闭和打开相同&#xff0c;先按 CtrlK&#xff0c;再按…

Typora全局搜素

目录 背景 解决方式 全局文件夹下搜索 方法一 方法二 单一文件下搜索 查找功能 1 查找整个单词 ​2 区分大小写 背景 有时需要在打开的文件夹中所有文件搜索某一单词&#xff0c;有时需要在一个文件下搜索 解决方式 全局文件夹下搜索 方法一 方法二 快捷键&#x…

linux 内存不足杀进程_内存不足:杀死进程或牺牲孩子

linux 内存不足杀进程现在是早上六点。 我清醒地总结了导致我太早唤醒电话的事件顺序。 这些故事开始时&#xff0c;我的电话警报响了。 困倦而脾气暴躁的我检查了电话&#xff0c;看我是否真的疯了以至于无法在凌晨5点设置唤醒警报。 不&#xff0c;这是我们的监视系统&#x…

为什么声明性编码使您成为更好的程序员

在许多情况下&#xff0c;具有功能组成的声明式解决方案提供了优于传统命令式代码的优越代码度量。 阅读本文并了解如何使用具有功能组成的声明性代码成为更好的程序员。 在本文中&#xff0c;我们将仔细研究三个问题示例&#xff0c;并研究用于解决这些问题的两种不同技术&am…

Ubuntu 16.04设置IP、网关、DNS

说明&#xff1a;在网上给的教程上面通常会有这样的一个误导思路&#xff0c;按照配置文件设置后会不生效的问题&#xff0c;甚至没有一点效果&#xff0c;经过排查发现Linux下设置IP这个话题的入口线索应该分为两种&#xff1a;1为Server版&#xff0c;2为Desktop版&#xff0…

eclipse调试NS3

Tips&#xff1a; 1&#xff0c; 安装eclipse时注意选择C开发组件&#xff1b; 环境配置参考&#xff1a;https://www.cnblogs.com/zlcxbb/p/3852810.html 第一步&#xff0c;新建C工程&#xff1b; 第二步&#xff0c;在project explorer中右键属性&#xff0c;如下图&…

高效的企业测试-单元和用例测试(2/6)

在本系列的第一部分中&#xff0c;我们看到了有效测试应满足的一些普遍适用的原则和约束。 在这一部分中&#xff0c;我们将仔细研究代码级单元测试以及组件或用例测试。 单元测试 单元测试验证单个单元&#xff08;通常是类&#xff09;的行为&#xff0c;而忽略或模拟该单元…

sublime text 光标移动行末/行首

背景 使用Sublime有移动至行首与文件首部的需求 解决方式 sublime text没有直接跳转至行首行尾的&#xff0c;因为不能判断哪里是段首和短位。但可以通过连续移动单词的方式快速到达行首或行尾。 快捷键 左键 // 向左移动一个字母 右键 // 向右移动一个字母 ctrl左键 //…

Typora文件快速打开与关闭文件

背景 Typora快速关闭与打开某个文件 快捷键 关闭&#xff1a; Ctrl W 在文件中打开&#xff1a; Contrl O 从相关历史记录中快速打开&#xff1a; Ctrl P 保存&#xff1a;CtrlS 另存为&#xff1a;CtrlShiftS 新建窗口&#xff1a;CtrlN

搜狗输入法更换字体与皮肤

图标上右键-更多-属性设置 效果&#xff1a; 注意&#xff1a;如果是新安装的字体&#xff0c;更换中文字体但其中列表没有显示&#xff0c;可以取消更换字体前面的对钩后&#xff0c;重新选择对钩&#xff0c;此时就显示新的中文字体了

javafx 8u40_JavaFX 8u20天的未来过去(始终在最前面)

javafx 8u40自从我发布有关JavaFX的主题以来已经有很长时间了。 因此&#xff0c;如果您仍在追随&#xff0c;那就太棒了&#xff01; 介绍 在这篇博客文章中&#xff0c;我想写一篇关于从JavaFX 8 update 20开始的非常酷的功能的博客&#xff0c;该功能使您的应用程序始终位于…

如何在内存序列化中使用Java深克隆对象

在我以前的文章中&#xff0c;我解释了深度克隆和浅层克隆之间的区别 &#xff0c; 以及复制构造函数和防御性复制方法比默认的Java克隆更好。 使用复制构造函数和防御性复制方法进行的Java对象克隆当然具有某些优势&#xff0c;但是我们必须显式编写一些代码才能在所有这些方…

手机更换必装软件

手机常用软件 1. 慢慢买 购物软件&#xff0c;复制商品链接&#xff0c;查看商品的历史价格与最低价格走势。并且内含优惠券&#xff0c;帮助省钱 2.清浊 用于清理系统垃圾与应用缓存&#xff0c;比系统自带的清理更加干净

复制网页内容

问题背景&#xff1a; 当网页复制东西时&#xff0c;可能因为某些原因导致无法复制。可以用以下方法解决 解决方法&#xff1a; 1. 按下F12&#xff0c;出现以下内容 2. 依次点击右上角三个点&#xff0c;弹出界面后点击shortcuts 3. 选择首选项后&#xff0c;选中Disable …

spring连接jdbc_在Spring JDBC中添加C3PO连接池

spring连接jdbc连接池是一种操作&#xff0c;其中系统会预先初始化将来要使用的连接。 这样做是因为在使用时创建连接是一项昂贵的操作。 在这篇文章中&#xff0c;我们将学习如何在Spring JDBC中创建C3P0连接池&#xff08;某人没有使用Hibernate&#xff09;。 Pom.xml <…