测试工具中的设计模式实例谈 - 装饰模式
2018-08-13 本文已影响0人
antony已经被占用
装饰模式
理想的装饰模式的UML图如下:
dp-decorator.png
理想的装饰器模式要求对客户端透明,只改变行为,不改变接口。
Hamcrest中的装饰模式
在Hamcrest中,为了表达更为复杂的Matcher逻辑,或者增强可读性,框架提供了类似Is\IsNot\Allof\AnyOf等装饰器, 实现了对于原有被装饰对象的功能增强,属于一种简化的装饰模式。
IsNot: NOT
AllOf:AND
AnyOf: OR
assertThat(cheese, is(equalTo(smelly)))
assertThat(cheese, is(not(equalTo(smelly))))
assertThat("myValue", allOf(startsWith("my"), containsString("Val")))
assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))
Matcher是hamcrest框架的核心,其的主要功能是传入一个类实例,以判断该实例是否能和当前Matcher所定义的逻辑匹配。BaseMatcher实现了接口Matcher,而其下的Matcher,如IsAnything、IsEqual、IsSame、IsNull等都是ConcreteComponent。右侧的Matcher,如Is、IsNot、AnyOf、AllOf)都是Decorator。
Matcher 类图(部分)
从上述案例,也可以看到Decorator Matcher可以套接其他的Decorator Matcher,如is(not(XXXMatcher)),用于表达更为复杂的逻辑,而每个类也可以只关注自己的逻辑,而把其他逻辑交给其他Matcher,保证了各自实现的原子性。
以下内容摘自Hamcrest的JavaDoc
public boolean matches(java.lang.Object arg)
Description copied from interface: Matcher
Evaluates the matcher for argument item.
This method matches against Object, instead of the generic type T. This is because the caller of the Matcher does not know at runtime what the type is (because of type erasure with Java generics). It is down to the implementations to check the correct type.
Parameters:
arg - the object against which the matcher is evaluated.
Returns:
true if item matches, otherwise false.
Is 类
Is类是个Matcher的装饰器,但这个Matcher没有提供更多的行为,它只是在描述前加入“is ”字符串,从而是错误信息的描述信息更加符合阅读习惯。
public static <T> Matcher<T> is(Matcher<T> matcher)
Decorates another Matcher, retaining its behaviour, but allowing tests to be slightly more expressive.
For example:
assertThat(cheese, is(equalTo(smelly)))
instead of:
assertThat(cheese, equalTo(smelly))
IsNot类
IsNot这个Matcher提供“非逻辑”,并在描述前加”not “字符串。
public static <T> Matcher<T> not(Matcher<T> matcher)
Creates a matcher that wraps an existing matcher, but inverts the logic by which it will match.
For example:
assertThat(cheese, is(not(equalTo(smelly))))
Parameters:
matcher - the matcher whose sense should be inverted
AnyOf
public static <T> AnyOf<T> anyOf(Matcher<T> first,
Matcher<? super T> second)
Creates a matcher that matches if the examined object matches ANY of the specified matchers.
For example:
assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))