matchers依赖_Hamcrest Matchers的高级创建

matchers依赖

介绍

上一次 ,我讨论了Hamcrest Matcher是什么,如何使用以及如何制作。 在本文中,我将解释创建Hamcrest Matchers的更多高级步骤。 首先,我将分享如何使您的匹配器更易于类型安全,然后介绍无状态匹配器的一些技术,最后是如何减少测试类的大量静态导入。 我还将给出一些有关命名静态工厂方法的快速提示。

类型安全匹配器

您可能已经在上次开发的matchs()方法中注意到了,我在注释中指出,我曾使用“ yoda条件”来避免null检查和类型检查。 首先,自己对yoda条件进行一些研究不会有什么坏处(我可能有一天会发表一篇有关它的文章,但不能保证),但是这里要注意的最大事情是某种类型检查和需要空检查。 这是因为matchs()方法接受一个对象,而不是泛型参数中指定的类型。

如Hamcrest的文档中所述:

此方法与Object匹配,而不是与通用类型T匹配。这是因为Matcher的调用者在运行时不知道类型是什么(由于Java通用类型已擦除类型)。

因此,我们需要确定传入的对象的类型。此外,我们还应确保没有传入任何空值(除非我们的特定Matcher可以这样做,但这非常罕见),或者在至少要确保传入的null不会导致NullPointerException。

但是有一种更简单的方法:TypeSafeMatcher。 如果扩展该类而不是BaseMatcher类,它将为您执行类型检查和null检查,然后将对象传递给仅采用泛型指定类型的匹配方法。

定义TypeSafeMatcher非常类似于我们上次定义Matcher的方式,但有一些区别:除了覆盖matchs()之外,您还可以替代使用通用类型而不是Object的matchesSafely()。 而不是覆盖describeMismatch(),而是覆盖describeMismatchSafely()。 可能没有一个新的describeTo()可能令人惊讶,但是看到它除了Description之外没有其他内容,因此不需要类型安全的版本。

否则,创建TypeSafeMatcher几乎是相同的。

不过,我不得不提我上周忘记的事情。 定义自己的Matcher的人不需要重写describeMismatch()或describeMismatchSafely()方法。 BaseMatcher和TypeSafeMatcher都具有那些方法的默认实现,这些方法的简单实现是仅输出“ was item.toString() ”(如果TypeSafeMatcher获得错误类型的项,则“ was of itemClassNameitem.toString()” )”。

这些默认实现通常足够好,但是如果要使用的类型没有toString()的有用实现,则使用您自己的不匹配消息来描述该项目的问题显然更有用。 即使类具有不错的toString()实现,我也总是这样做,因为它可以更快地解决问题。

有关其他可扩展匹配器类的说明

Hamcrest核心库中还有其他几个Matcher类,供用户从中扩展。 这些有几种口味。

首先,是CustomMatcher和CustomTypeSafeMatcher。 这些设计用于通过匿名类一次性创建Matchers。 他们可能是有用的,但我更愿意总是在情况下,正确执行我曾经确实需要它一次。

接下来,有DiagnosingMatcher和TypeSafeDiagnosingMatcher,它们使您可以在match()方法中创建不匹配描述。 这似乎是用一块石头杀死两只鸟的好方法,但是我有几块牛肉:1)它违反了SRP 2)如果存在不匹配,它再次调用matchs()方法只是为了填充在不匹配说明中。 因此,第一个调用忽略获取描述,第二个调用忽略匹配。

您可以扩展的最后一个特殊的Matcher是FeatureMatcher。 这可能非常有用,但要理解起来很复杂(我不确定自己是否正确理解–直到我尝试自己动手做一个或阅读如何做一个为止)。 如果我弄清楚并获得了很好的理解,我将在这里为您写另一篇文章。

无状态匹配器

任何不需要将任何内容传递给其构造函数的Matcher(因此,它是静态工厂方法)都是无状态Matcher。 它们与其他Matcher相比有一个很小的优势,因为您只需要在任何时候存在一个实例,就可以在需要使用该Matcher的任何时间重用它。

这是一个非常简单的补充。 您需要做的就是创建该类的静态实例,并使您的静态工厂返回该实例,而不是调用构造函数。 库实际附带的IsEmptyString Matcher可以做到这一点(上一次我们的示例没有这样做,但是为了简单起见)。

减少静态进口数量

用Hamcrest Matchers编写了相当多的测试后,您可能会注意到文件顶部有很多静态导入。 一段时间后,这可能会成为很大的麻烦事,所以让我们看一下可以减轻此问题的方法。

实际上,这几乎与上一个解决方案一样简单。 您可以通过创建实质上为您执行此操作的新类来减少静态导入。 这个新类具有烦人的静态导入,但随后定义了自己的静态工厂方法来委托给原始对象。 这是将一些核心Matchers组合到一个地方的示例:

import org.hamcrest.core.IsEqual;
import org.hamcrest.core.IsNull;
import org.hamcrest.core.IsSame;
import org.hamcrest.Matcher;public class CoreMatchers
{public static  Matcher equalTo(T object) {return IsEqual.equalTo(object);}public static Matcher notNullValue() {return IsNull.notNullValue();}public static  Matcher notNullValue(Class type) {return IsNull.notNullValue(type);}public static Matcher nullValue() {return IsNull.nullValue();}public static  Matcher nullValue(Class type) {return IsNull.nullValue(type);}public static  Matcher sameInstance(T target) {return IsSame.sameInstance(target);}public static  Matcher theInstance(T target) {return IsSame.theInstance(target);}
}

然后,要使用任何或所有Matcher,只需静态导入CoreMatchers。*还有一种生成这些组合Matcher类的方法,如官方Hamcrest教程所示 。 我不会继续讨论它,因为它不在本文讨论范围之内,而且我也不喜欢它。

结束提示:命名

如果您阅读了官方的Hamcrest教程和/或查看了内置的Matchers,您可能会注意到静态工厂方法的命名趋势。 通用语法匹配“断言testObjectfactoryMethod ”。 方法名称的语法通常设计为可以在“ is”之前使用的当前时态动作。在命名自己的静态工厂方法时,通常应遵循此约定,但实际上我建议将“ is”放入名称中已经。 这样,Matcher的用户无需将您的方法嵌套在is()方法内。 但是,如果执行此操作,则还需要创建反函数。 允许使用is()方法包装Matcher的原因是,因此您也可以将其包装在not()方法中,以测试已经测试的内容的逆函数。 这将导致类似“断言testObject不是factoryMethod ”的句子。如果您认为遵循约定对特定的Matcher过于严格,则只需确保使用当前的时态操作测试即可。 例如,我做了一个匹配器,检查是否抛出了一个异常,该异常的静态工厂方法是throwsA()。 我只是不喜欢将它命名为throwingA()以便与“ is”一起使用。 但是,如果再次违反约定,则必须确定要创建一个静态静态工厂方法。 例如,如果您要实现自己的逆工厂,最简单的方法通常是用not()包装正工厂。 因此,我的nottThrowA()方法将返回not(throwsA())。 不过要小心:有时候,将正负误转实际上并不能给出您想要的正确逆。

奥托罗

好吧,这就是我为您准备的。 如果您想让我继续谈论Hamcrest Matchers,请在评论中告诉我。 否则,您可以在其github页面上的Hamcrest Matchers上进行自己的研究。下周,我将讨论如何让您的Hamcrest Matchers以类似于AssertJ断言的流畅方式检查多个事情。

翻译自: https://www.javacodegeeks.com/2015/01/advanced-creation-of-hamcrest-matchers.html

matchers依赖

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

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

相关文章

深入浅出讲解C语言#define宏定义应用及使用方法

在C语言中,我们使用#define来定义宏。在C程序编译的预处理阶段,预处理器会把宏定义的符号替换成指定的文本。不带参数的宏关于宏最常见的就是用来定义数值常量的名称,即没有参数的宏定义,采用如下形式:1#define 宏名称…

安卓系统双屏异显_Android 双屏异显实现的三种方式

在各种产品脑洞大开的时代,需求也是日益新异,笔者最近开发了一套双屏异显app。现在做一些总结1.双屏异显第一种实现方式(官方提供的Presentation)Android 提供了一个叫 Presentation 类,来实现第二屏, 继承 Presentation 实现第二…

hazelcast入门教程_Hazelcast入门指南第5部分

hazelcast入门教程这是我撰写的有关Hazelcast的一系列文章的延续。 我强烈建议您阅读其他内容: 第1 部分 , 第2 部分 , 第3 部分和第4部分 。 一气呵成的东西 这篇文章中没有Hazelcast专用代码。 让我重复一遍。 这篇文章中没有Hazelcast专用…

单片机C语言编程:.H文件与.C文件的关系!

一个.C文件对应一个.H文件是一种良好的编程习惯,那么.C和.H文件之间的关系是怎么样的呢?一、.H文件与.C文件的关系:迄今为止,写过的程序都是一些很简单的程序,从来没有想到要自己写.H文件,也不知道.H文件到…

python编程快速上手-----让繁琐工作自动化_Python编程快速上手让繁琐工作自动化--逗号代码和字符图网格...

逗号代码假定有下面这样的列表:spam [apples, bananas, tofu, cats]编写一个函数,它以一个列表值作为参数,返回一个字符串。该字符串包含所有表项,表项之间以逗号和空格分隔,并在最后一个表项之前插入and。例如将前面…

spring依赖注入_Spring的依赖注入陷阱

spring依赖注入Spring框架中有三种注入变量: 基于二传手的注射 基于构造函数的注入 基于现场的注入 这些机制中的每一种都有优点和缺点,并且不仅只有一种正确的方法。 例如现场注入: Autowired private FooBean fooBean;在生产代码中使用…

C语言中的“悬空指针”和“野指针”是什么意思?

提起C语言大部分开发者很自然就会想到指针二字,没错,作为C的核心和灵魂,它的地位咱们就不再赘述了,今天我们想跟大家讲的是指针中的两个特有名词:“悬空指针”和“野指针”。1 悬空指针C语言中的指针可以指向一块内存&…

java zip解压_Java语言入门第一课

Java最初的目标是嵌入式设备,不过在嵌入式设备方面并未取得成功。失之东隅,收之桑榆,Java却在Web领域被广泛接受。近年来,随着Java在服务器领域的不断突破,让这门语言越来越流行。有人喜欢Java的纯面向对象&#xff0c…

怎么用c语言做出等妖三角形_初二数学培优,怎么用顶点坐标求三角形面积?割补法这样用很简单...

点击右上角关注“陈老师初中数理化”分享学习经验,一起畅游快乐的学习生活。根据顶点坐标求解三角形的面积是初二数学的重要知识点,本文就例题详细解析这类题型的解题思路,希望能给初二学生的数学学习带来帮助。例题如图,在平面直…

restful xml_使用入站适配器公开HTTP Restful API。 第1部分(XML)

restful xml1.简介 这篇文章的目的是使用Spring Integration HTTP入站适配器实现HTTP Restful API。 本教程分为两个部分: XML配置示例(同一篇文章)。 Java DSL示例。 这将在本教程的下一部分中进行说明,展示如何使用Spring Int…

C语言的位域

位域是什么?有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位。正是基于这种考虑,C语言又提供了一种叫做位域的…

xp精简工具_办公人士需要精简Win10吗?

首先要说自己的系统需求1,笔记本是主要生产力工具,靠它做方案,联系网络社交;2,会偶尔(一月2-3次)用到PS,AI,PR等软件;3,文件多,版本多…

matlab 删除路径_MATLAB使用教程(一)—新手来看

前言:在这里,本人默认大家已经安装好了MATLAB软件,如果没有,请自行安装。注意事项:新手容易犯错,打开MATLAB之后,请按CTRLQ这个组合键,是不是发现你的MATLAB关闭了?对&am…

数据的gzip压缩解压缩_使用GZIP和压缩数据

数据的gzip压缩解压缩抽象 我们都知道用zip或gzip压缩文件的含义。 但是在Java中使用压缩文件并不像您想的那样简单,特别是如果您不是直接使用文件而是压缩流数据时。 我们会去: 如何将字符串转换为压缩/压缩字节数组,反之亦然 创建用于读取…

C语言开发单片机为啥都是全局变量形式?

01前言全局变量简直就是嵌入式系统的戈兰高地。冲突最激烈的双方是:1. 做控制的工程师;2. 做非嵌入式的软件工程师。02做控制的工程师特点他们普遍的理解就是“变量都写成全局该有多方便”。我之前面试过一个非常有名的做控制实验室里出来的PhD/Master&a…

ajax get请求_python测试开发django50.jquery发送Ajax请求(get)

前言有时候,我们希望点击页面上的某个按钮后,不刷新整个页面,给后台发送一个请求过去,请求到数据后填充到html上,这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。Ajax可以完美的实现。…

primefaces_PrimeFaces Mobile入门

primefaces介绍 如果您已经开发了利用PrimeFaces的应用程序,或者打算开发可在台式机和移动设备上使用的Web应用程序,请考虑将PrimeFaces Mobile用于您的移动实施。 这篇博客文章将介绍一些基础知识,以帮助您开始为现有的PrimeFaces应用程序开…

C语言指针这些使用技巧值得收藏!

指针用的好犹如神助,用不好会让你叫苦连连,但大多数人是用不好指针的,所以后来的很多语言都把指针封装,屏蔽。比如JAVA,java是没有指针的,但是很多地方都用到指针,不过不对用户开放,…

如何用python实现地图定位_基于 PyQt5 实现地图中定位相片拍摄位置

项目简介:本次项目主要学习了如何查找相片中的 Exif 信息,并通过 Exif 信息中的 GPS 数据在百度地图中进行定位标点,以确定相片的拍摄地点。本次实验的目的旨在通过包含 GPS 信息的相片进行取证调查,当然个人娱乐也可以&#xff0…

mysql数据库中的int类型_MySQL中int(M)和tinyint(M)数值类型中M值的意义

在一开始接触MySQL数据库时,对于int(M)及tinyint(M)两者数值类型后面的M值理解是最多能够插入数据库中的值不能大于M;后来工作后,也是一边学习一边使用,之后的理解是其中的M的意思是插入数据库中的值的字符长度不能大于M&#xff…