1.概述
Hamcrest是Java生态系统中用于单元测试的著名框架。它捆绑在JUnit中,简单地说,它使用现有的谓词(称为匹配器类)来做出断言。
在本教程中,我们将这样做探索Hamcrest API并学习如何利用它来为我们的软件编写更整洁、更直观的单元测试。
2.Hamcrest设置
我们可以使用Hamcrest通过将以下依赖项添加到pom.xml文件:
<依赖> < groupId > org。hamcrest-all 1.3 依赖>
始终可以找到该库的最新版本这里。
3.一个示例测试
Hamcrest通常使用junit以及用于制作断言的其他测试框架。具体而言,而不是使用junit很多断言方法,我们只使用API的single为了语句与适当的匹配器。
让我们来看看测试两个的一个例子字符串S表示是否相等。这应该给我们一个清晰的概念金宝搏官网188beHamcrest适合于一种测试方法:
public class StringMatcherTest {@Test public void given2strings_whenequal_threct () {String a = "foo";String b = "FOO";为了(a, equalToIgnoringCase (b));}}
在下面的章节中,我们将看一看其他几个常见的匹配器Hamcrest报价。
4.的对象匹配器
Hamcrest提供用于在任意Java对象上进行断言的匹配器。
断言toString方法的一个对象返回指定的字符串:
@Test public void givenbean_whentostringreturnnsrequiredstring_threct (){Person Person =new Person("Barrack", "Washington");字符串str = person.toString ();为了(人,hasToString (str));}
我们还可以检查一类是另一级的子类:
@Test public void given2classes_whenoneinheritsfromother_thcorrect (){assertThat(Cat.class,typeCompatibleWith(Animal.class));}}
5.Bean匹配器
我们可以使用Hamcrest的Bean匹配器来检查Java Bean的属性。
假设如下人豆:
public class Person {String name;字符串地址;public Person(String personName, String personAddress) {name = personName;地址= personAddress;}}
我们可以检查Bean是否具有属性,的名字像这样:
@Test public void givenbean_whenhasvalue_threcert () {Person Person = new Person("Bae金宝搏188体育ldung", 25);为了(人,hasProperty("名称"));}
我们也可以检查是否人有地址属性,初始化为New York:
@Test public void givenbean_whenhascorrectvalue_thcorrect () {Person Person = new Person("Ba金宝搏188体育eldung", " new York");assertThat(person, hasProperty("address", equalTo("New York")));}
我们也可以检查两个人对象以相同的值构造:
@test public void给gent2beans_whenhavingsamevalues_thengorrect(){person person1 =新人(“Baeldung”,“纽金宝搏188体育约”);人员2 =新人(“Baeldung”,“纽约”);金宝搏188体育assertthat(person1,smarepropertyvaluesas(person2));}
6.的收藏匹配器
Hamcrest提供用于检查的匹配收藏年代。
简单的检查,看看是否收藏是空的:
@Test public void givencollection_whenempty_threct () {List emptyList = new ArrayList<>();为了(emptyList、空());}
检查a集合:
@Test public void givenAList_whenChecksSize_thenCorrect() {List hamcrestMatchers = array;asList("collections", "beans", "text", "number");为了(hamcrestMatchers hasSize (4));}
也可以用它来断言数组具有所需的大小:
@Test public void givenarray_whencheckssize_thcorrect () {String[] hamcrestMatchers = {"collections", "beans", "text", "number"};为了(hamcrestMatchers arrayWithSize (4));}
检查是否一个收藏包含给定的成员,无论顺序如何:
@Test public void givenalistandvalues_whencheckslistforvenvalues_threct () {List hamcrestMatchers = array . getarray ();asList("collections", "beans", "text", "number");assertThat(hamcrestMatchers, containsInAnyOrder("beans", "text", "collections", "number"));}
进一步断言收藏成员按顺序排列:
@test public void tendalistandvalues_whencheckslistorgivenvalueswithorder_thencorrect(){list hamcrestmatchers = arrays.aslist(“集合”,“beans”,“文本”,“编号”);Assertthat(HamcrestMatchers,包含(“集合”,“豆类”,“文本”,“编号”));}
要检查数组是否具有单个给定元素:
@Test public void givenarrayandvalue_whenvaluefoundinarray_threct () {String[] hamcrestMatchers = {"collections", "beans", "text", "number"};为了(hamcrestMatchers hasItemInArray(“文本”));}
我们也可以为相同的测试使用一个替代的匹配器:
@test public voidedvalueandarray_whenvalueisoneofarrayelements_thencorrect(){string [] hamcrestmatchers = {collections“,”beans“,”text“,”编号“};Assertthat(“文本”,Isoneof(Hamcrestmatchers));}
或者我们可以用不同的匹配者这样做:
@Test public void givenvalueandarray_whenvaluefoundinarray_threct () {String[] array = new String[] {"collections", "beans", "text", "number"};为了(“豆”,型号(数组));}
我们也可以检查数组中是否包含给定的元素,无论顺序如何:
@Test public void givenarrayandvalues_whenvaluesfoundinarray_threct () {String[] hamcrestMatchers = {"collections", "beans", "text", "number"};assertThat(hamcrestMatchers, arrayContainingInAnyOrder("beans", "collections", "number", "text"));}
检查数组是否包含给定的元素,但顺序如下:
@Test public void givenarrayandvalues_whenvaluesfoundinarrayinorder_threct () {String[] hamcrestMatchers = {"collections", "beans", "text", "number"};assertThat(hamcrestMatchers, arraycontains ("collections", "beans", "text", "number"));}
当我们的收藏是一个地图,我们可以在这些相应的函数中使用以下匹配器:
要检查它是否包含一个给定的键:
@test public voidedmapandkey_whenkeyfoundinmap_thencorrect(){map map = new hashmap <>();Map.put(“Blogname”,“B金宝搏188体育aeldung”);assertthat(地图,haskey(“爆炸ame”));}
和一个给定的值:
@Test public void givenmapandvalue_whenvaluefoundinmap_threct () {Map Map = new HashMap<>();Map.put(“Blogname”,“B金宝搏188体育aeldung”);为了(地图,hasValue (baeldung "金宝搏188体育));}
最后是一个给定的条目(key, value):
@test public voidedmapandentry_whenentryfoundinmap_thencorrect(){map map = new hashmap <>();Map.put(“Blogname”,“B金宝搏188体育aeldung”);assertthat(地图,hasentry(“blogname”,“bae金宝搏188体育ldung”));}
7.数量匹配器
的数量匹配器用于对变量进行断言数量类。
检查比...更棒条件:
@Test public void givenaninteger_whengreaterthan0_thorrect () {assertThat(1, greaterThan(0));}
检查比...更棒或者等于条件:
@Test public void givenaninteger_whengreaterthanoreqto5_thorrect () {assertThat(5, greaterThanOrEqualTo(5));}
检查不超过条件:
@test public void edainaninteger_whenlessthan0_thencorrect(){assertthat(-1,lessthan(0));}
检查不超过或者等于条件:
@Test public void givenaninteger_whenlessthanoreqto5_thorrect () {assertThat(-1, lessThanOrEqualTo(5));}
检查接近条件:
@test public void gendadaude_whencloseto_thencorrect(){assertthat(1.2,closeto(1,0.5));}
让我们密切关注最后一位选手,接近。第一个参数,即操作数,是与目标进行比较的参数,第二个参数是与操作数的允许偏差。这意味着如果目标是操作数+偏差或操作数偏差,则测试将通过。
8.匹配器的文本
断言在字符串S变得更容易,更整齐,更直观Hamcrest的文本匹配器。我们将在本节中查看它们。
检查是否一个字符串是空的:
@Test public void givenstring_whenempty_thcorrect () {String str = "";为了(str isEmptyString ());}
检查是否一个字符串为空或空值:
@test public void gendstring_whenemptyornull_thengorrect(){string str = null;assertthat(str,iSemptyornullstring());}
检查两个平等字符串S忽略空白:
@test public void给gent2strings_whenequalRegardlesswherwhiteSpace_thengorrect(){string str1 =“text”;String str2 = " text ";asserthat(str1,stralignorionwhiteSpace(str2));}
我们还可以检查给定字符串中是否存在一个或多个子字符串字符串在给定的顺序:
@test public void给genstring_whencontainsgivensubstring_thencorrect(){string str =“calligraphy”;assertthat(str,stringContainsinorder(arrays.aslist(“呼叫”,“图形”))));}
最后,我们可以检查两个的平等字符串无论情况如何:
@Test public void given2strings_whenequal_threct () {String a = "foo";String b = "FOO";为了(a, equalToIgnoringCase (b));}
9.核心API
的Hamcrest核心API将由第三方框架提供商使用。但是,它为我们提供了一些伟大的构造,使我们的单元测试更可读,也可以轻松使用的一些核心匹配器。
可读性与是匹配器上的构造:
@Test public void given2strings_whenisequalregardless whitespace_threct () {String str1 = "text";String str2 = " text ";为了(str1 (equalToIgnoringWhiteSpace (str2)));}
的是构造在简单的数据类型上:
@Test public void given2strings_whenisequal_threct () {String str1 = "text";String str2 = "text";为了(str1 (str2));}
否定的不匹配器上的构造:
@test public void gent2strings_whenisnotequalRegardlessWhiteSpace_thengorRect(){string str1 =“text”;字符串str2 =“文本”;assertthat(str1,不是(stronignorialwhiteSpace(str2)));}
的不构造在简单的数据类型上:
@Test public void given2strings_whennotequal_threct () {String str1 = "text";String str2 = "文本";为了(str1,不是(str2));}
检查一个字符串包含给定的子字符串:
@test public voidedastrings_whencontainsanothotgivenstring_thencorrect(){string str1 =“calligraphy”;String str2 = "调用";assertthat(str1,containstring(str2));}
检查一个字符串以给定的子字符串开始:
@Test public void givenstring_whenstartswithanothergivenstring_threct () {String str1 = "书法";String str2 = "调用";为了(str1 startsWith (str2));}
检查一个字符串以给定的子字符串结束:
@Test public void givenstring_whenendswithanothergivenstring_threct () {String str1 = "书法";String str2 = "phy";为了(str1 endsWith (str2));}
检查二是否二对象S是相同的实例:
@Test public void given2objects_whensameinstance_threct () {Cat Cat =new Cat(); / /使用实例为了(猫,sameInstance (cat));}
检查一下对象是给定类的实例:
@Test public void givenanobject_wheninstanceofgivenclass_threct () {Cat Cat =new Cat();为了(猫,instanceOf (Cat.class));}
检查是否所有成员a收藏满足条件:
@Test public void givenlist_wheneachelementgreaterthan0_thorrect () {List List = Arrays. getarray ();asList(1、2、3);int baseCase = 0;为了(列表,everyItem (greaterThan (baseCase)));}
检查一下字符串不是空值:
@Test public void givenstring_whennotnull_threct () {String str = "notnull";为了(str notNullValue ());}
将条件链在一起,当目标满足任何条件时测试通过,类似于逻辑OR:
@Test public void givenstring_whenmeetsanyofgivenconditions_threct () {String str = "书法";String start = "call";字符串结束= "foo";为了(str,任何(startsWith(开始),containsString(结束)));}
将条件链在一起,当目标满足所有条件时测试通过,类似逻辑AND:
@test public void给gendstring_whenmeetsallofgivenconditions_thencorrect(){string str =“calligraphy”;String start = "call";字符串终止=“phy”;Assertthat(str,allof(startswith(startscith),endscith(end)));}
10.自定义匹配器
我们可以通过扩展来定义自己的匹配器typesAfeMatcher.。在本节中,我们将创建一个自定义匹配器,它允许测试仅在目标为正整数时通过。
public class IsPositiveInteger extends TypeSafeMatcher {public void descripbeto (Description Description) {Description。追加文本(“一个正整数”);} @Factory public static Matcher isAPositiveInteger(){返回新的IsPositiveInteger();} @Override protected boolean matchesSafely(Integer Integer) {return Integer > 0;}}
我们只需要实施matchSafely检查目标确实是正整数的方法和方法描述方法,该方法在测试未通过时生成失败消息。
下面是一个使用我们新的自定义匹配器的测试:
@Test public void giveninteger_whenapositivevalue_thcorrect () {int num = 1;为了(num isAPositiveInteger ());}
这是一个失败消息,因为我们传递了一个非正整数:
java.lang.assertionError:预期:正整数但是:是<-1>
11.结论
在本教程中,我们有探索了Hamcrest API并学习了如何用它编写更好、更易于维护的单元测试。
所有这些示例和代码片段的完整实现可以在我的身上找到Hamcrest Github项目。