kotlin制作图形验证码
本文是对Java中较旧版本的重写。 这是在Kotlin中完成的。
首先,我应该快速解释一下Hamcrest Matcher是什么。 在进行单元测试时,测试框架随附的内置断言类型通常非常有限。 它们使一个人很容易以多个断言来本质上检查一件事。 即使没有多个断言,这些断言也不是最流利的阅读方式,也无法准确告诉您要检查的内容。
那就是Hamcrest Matchers进入的地方(以及其他断言库,但是我们现在正在考虑hamcrest)。 从本质上讲,它们使您可以定义自己的更健壮和更流畅的断言。 例如,如果您正在测试某个方法是否正确返回一个空的String,则该测试可能类似于以下内容:
@Test fun testUsingMatcher() {
val string = methodThatShouldReturnAnEmptyString();
assertThat(string, isEmptyString()); }
查看该断言行。 一旦您忽略了所有“标点符号”,它的读音几乎就像是英语。 “声明该字符串为空字符串。” 一些匹配者比其他人更努力地阅读英语,但是他们都读得很好,以使它们易于理解。
我们将介绍基础知识,并在此过程中重新创建IsEmptyString
匹配器。 首先,此匹配器将从<code-BaseMatcher开始。 这样,让我们开始构建。
Hamcrest Matcher基本上有4个部分:静态工厂方法,断言,传递的断言的描述和失败的断言的描述。 最后两个是我撰写本文的最大原因。 我花了一些时间才弄清楚该怎么做的“最佳实践”。 但是我们将从头开始。
老实说,在Kotlin中,静态工厂方法不是问题。 主要原因是不需要new
关键字,但Kotlin还是不使用它。 如果您还计划使其向后兼容以在Java代码中使用,那么我建议仍然使用它。 如果没有,那么您唯一需要解决的就是大写。 您可以在断言中使用大写的类名吗? 如果是这样,那么您就很容易。 如果不是,则可以选择使类名小写(从而违反约定)或添加静态工厂方法。 Kotlin如此慷慨地提供了import ... as ...
选项。
如果要创建静态工厂,我实际上建议将其作为顶级函数而不是作为companion object
。 这使得它自动成为Java用户的静态方法,因此他们可以执行很好的静态导入,并且可以避免奇怪的伴随语法(尤其是与@JvmStatic
配对使用)。
该函数的代码很简单:
fun isEmptyString() = IsEmptyString()
总体而言,该方法非常平淡且明显。 我还没有遇到一个没有的实例。 使用Kotlin允许的所有快捷方式,例如跳过返回类型和使用单个表达式形式,它也特别快捷方便。
接下来,我们需要断言,这是通过matches()方法完成的。 这是匹配器的实际工作,正在运行实际检查。 注意,这并不意味着抛出AssertionError
; 这就是assertThat()
方法的工作。 此方法仅返回一个Boolean
指示输入是否与Matcher测试的想法匹配。
该方法的输入来自assertThat()
方法中的第一个参数。 当assertThat()
运行提供的匹配器的matches()
方法时,它将该参数传递给它。 matches()
方法接受一个Object
(Kotlin中的Any
),而不接受泛型指定的类型。 这是因为我没有研究过Java泛型的一些怪异“功能”,所以我无法解释。 我只是想让您知道,在扩展BaseMatcher
时,通常必须进行某种类型检查。
这是IsEmptyString
matches()
方法的实现:
override fun matches(actual: Any?): Boolean =
if (actual is String)
actual == ""
else
false
在这种情况下,仅此而已–它只是检查它是否为空String。
现在我们必须做两个描述。 由于它们是相似的,因此我们将一并进行。 这两个描述分别是describeTo()
和describeMismatch()
。 describeTo()
方法用于描述匹配器期望的内容。 在这种情况下,这是一个空String
。 describeMismatch()方法用于描述实际结果,通常只是输出给定的对象。
仅当匹配失败并且抛出AssertionError
这两种描述方法才起作用。 assertThat()
方法然后为失败的断言构建一个Description。 格式如下:
<user-provided reason> Expected: <result of describeTo>
but: <result of describeMismatch>
用户提供的原因可以通过先将String参数发送到assertThat()
方法中来定义。
如您所见,输出的格式使得人们不需要在描述中包括任何无关的信息,例如其描述的是匹配还是不匹配。
这两种方法的怪异之处在于它们本身并不使用String
。 他们使用所谓的Description
对象,我可以肯定的是,它们允许他们1)避免过多的String
串联,因为它看起来有点像StringBuilder
并且2)可能使用其他种类的Description
(这是一个接口) )对象在不同的工具中显示的内容有所不同。
因此,这是这些“描述”方法的实现:
override fun describe(description: Description) {
description.appendText( "empty String" ) } override fun describeMismatch(item: Any?, description: Description) {
description.appendValue(item) }
您会注意到, Description
对象具有两个方法appendText()
和appendValue()
。 我只用过这两个,即使它还有更多。 这些仅在少数情况下适用,如果您有兴趣,请检查一下。 如果不清楚, appendText
将接受一个String
并将其附加到描述中已经存在的内容的末尾,就像StringBuilder
。 而appendValue
似乎在传入的任何内容上运行toString()
并将其追加。
而已! 你完成了。 您现在有一个正在工作的Hamcrest Matcher。 有关更多信息,请访问官方网站 。 但是,如果您要进行研究,则会发现我们没有正确地重新创建内置的IsEmptyString
Matcher。 有一些技术要先进一些(这会使这篇文章变得比我所适应的更长)。 我将在下一篇文章中介绍它们。
翻译自: https://www.javacodegeeks.com/2020/02/how-to-make-your-own-hamcrest-matchers-in-kotlin.html
kotlin制作图形验证码