自定义hamcrest Matcher
在Junit中使用assertThat方法的时候第二个参数是一个hamcrest的Matcher 让Junit断言具有了很高的灵活性和可扩展性。
这里扩展一个大小比较的Matcher
-
首先自定义一个Matcher继承hamcrest的org.hamcrest.BaseMatcher
-
分别实现matches 和 describeTo
@Override public boolean matches(Object actual) { // 是否通过assert } @Override public void describeTo(Description description) { // 没有通过显示的信息 }
-
在Junit使用即可
代码实现
功能: 实现一个大于 大于等于 小于 小于等于的Matcher
这里我使用了策略模式将具体的比较行为抽离成一个比较器,核心就是根据matches方法返回的boolean值判断是否断言成功
public class ComparatorMatcher<T extends Number> extends BaseMatcher<T> {
public class ComparatorMatcher<T extends Number> extends BaseMatcher<T> {
// 期望值
private final T expected;
private final Comparator<? super Number> comparator;
private Object actual;
public ComparatorMatcher(T expected, Comparator<Number> comparator) {
this.expected = expected;
this.comparator = comparator;
}
@Override
public boolean matches(Object actual) {
this.actual = actual;
if (actual instanceof Number) {
Number actualNum = (Number) actual;
return comparator.compare(expected, actualNum);
}
throw new UnsupportedOperationException(" not a number ");
}
@Override
public void describeTo(Description description) {
description.appendText(String.format(" compactor error expected %s actual %s", String.valueOf(this.expected), String.valueOf(actual)));
}
@Factory
public static <T extends Number> ComparatorMatcher<T> gt(T expected) {
return new ComparatorMatcher<>(expected, new GtComparator<>(false));
}
@Factory
public static <T extends Number> ComparatorMatcher<T> lt(T expected) {
return new ComparatorMatcher<>(expected, new LtComparator<>(false));
}
@Factory
public static <T extends Number> ComparatorMatcher<T> gte(T expected) {
return new ComparatorMatcher<>(expected, new GtComparator<>(true));
}
@Factory
public static <T extends Number> ComparatorMatcher<T> lte(T expected) {
return new ComparatorMatcher<>(expected, new LtComparator<>(true));
}
}
// 比较器接口
public interface Comparator<T extends Number> {
boolean compare(T excepted, T actual);
}
// 大于比较器
public class GtComparator<T extends Number> implements Comparator<T> {
private boolean isGte;
public GtComparator(boolean isGte) {
this.isGte = isGte;
}
@Override
public boolean compare(T excepted, T actual) {
if (isGte) {
return actual.doubleValue() >= excepted.doubleValue();
}
return actual.doubleValue() > excepted.doubleValue();
}
}
// 小于比较器
public class LtComparator<T extends Number> implements Comparator<T> {
private boolean isLte;
public LtComparator(boolean isLte) {
this.isLte = isLte;
}
@Override
public boolean compare(T excepted, T actual) {
if (isLte) {
return actual.doubleValue() <= excepted.doubleValue();
}
return actual.doubleValue() < excepted.doubleValue();
}
}
// Junit 测试
public class TestCustomComparatorMatcher {
@Test
public void testMyMatcher() {
assertThat(2, gt(1));
assertThat(2, gte(2));
assertThat(2, lt(4));
assertThat(2, lte(4));
assertThat(2, lte(2));
}
}