Hamcrest 学习笔记

Hamcrest 学习笔记

TODO

Junit

JUnit框架用一组assert方法封装了一些常用的断言。这些assert方法可以帮我们简化单元测试的编写。这样的话,Junit就可以根据这些断言是否抛出 AssertionFailedError 错误来判断测试用例的执行结果。

Hamcrest

使用过Junit 的应该有过体验:在实际开发中,一些基本的断言,如eqaul,null,true它们的可读性并不是很好。而且很多时候我们要比较对象、集合、Map等数据结构。这样我们要么进行大段的字段获取再断言。或者干脆自己编写表达式并断言其结果。
JUnit4.4引入了Hamcrest框架,Hamcest提供了一套匹配符Matcher,这些匹配符更接近自然语言,可读性高,更加灵活。

Hamcrest 提供了大量被称为“匹配器”的方法。其中每个匹配器都设计用于执行特定的比较操作。Hamcrest的可扩展性很好,让你能够创建自定义的匹配器。最重要的是,JUnit也包含了Hamcrest的核心,提供了对Hamcrest的原生支持,可以直接使用Hamcrest。当然要使用功能齐备的Hamcrest,还是要引入对它的依赖。

Tutorial: http://hamcrest.org/JavaHamcrest/tutorial
API: http://hamcrest.org/JavaHamcrest/javadoc/2.1/

Utils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.ArrayList;
import java.util.List;

public class Utils {
public static List<Integer> fibonacci(int n) {
int a = 1, b = 1, c = 0;
List<Integer> result = new ArrayList<>();

for (int i = 1; i <= n; i++) {
if (i == 1) {
result.add(a);
} else if (i == 2) {
result.add(b);
} else {
c = a + b;
a = b;
b = c;
result.add(c);
}
}

return result;
}
}
UtilsTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

import static Matchers.ListMatcher.aList;
import static Matchers.NumberMatcher.aNumber;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class UtilsTest {
private List<Integer> expected;

@Before
public void initExpected() {
expected = Arrays.asList(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368);
}

@Test
public void testFibonacciByJunit() {
List<Integer> actual = Utils.fibonacci(expected.size());

// Way 1
Assert.assertEquals(expected.size(), actual.size());

int index = 0;
for (Integer expect : expected) {
Assert.assertEquals(expect, actual.get(index));
index++;
}

// Way 2
Assert.assertEquals(expected, actual);
}

@Test
public void testFibonacciByHamcrest() {
List<Integer> actual = Utils.fibonacci(expected.size());

// Way 3
assertThat(actual, not(aNumber()));
assertThat(actual, is(aList()));
assertThat(actual, equalTo(expected));
}
}
Matchers/NumberMatcher.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package Matchers;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

public class NumberMatcher extends TypeSafeMatcher {

public void describeTo(Description description) {
description.appendText("is a number");
}

public static Matcher aNumber() {
return new NumberMatcher();
}

@Override
protected boolean matchesSafely(Object o) {
return o instanceof Integer || o instanceof Double;
}
}
Matchers/ListMatcher.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package Matchers;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import java.util.List;

public class ListMatcher extends TypeSafeMatcher {

public void describeTo(Description description) {
description.appendText("is a list");
}

public static Matcher aList() {
return new ListMatcher();
}

@Override
protected boolean matchesSafely(Object o) {
return o instanceof List;
}
}

harmcrest的核心类从Matchers转为CoreMatchers。用户在使用的时候需要注意更新。

当使用assertThat时,静态导入时,导入的路径变为:

1
import static org.hamcrest.CoreMatchers.*;

封面来源: pixabay, free for commercial use.

作者

iMaeGoo

发布于

2019-04-27

更新于

2019-04-27

许可协议

CC BY 4.0

评论