JUnit源码解析(5)

发表于:2016-10-04来源:saymagic作者:saymagic点击数: 标签:junit
runner.run(notifier); } 很是明了,直接滴啊用runner的run方法。这样,如果这个runner的实例仍然是Suite,则会继续向里运行,如果这个runner为BlockJUnit4ClassRunner,这
    runner.run(notifier);
}
很是明了,直接滴啊用runner的run方法。这样,如果这个runner的实例仍然是Suite,则会继续向里运行,如果这个runner为BlockJUnit4ClassRunner,这执行我们前面分析的逻辑。这里有个问题是,那这个runner是如何生成的呢?这就要看Suite的构造函数:
 
protected Suite(Class<?> klass, Class<?>[] suiteClasses) throws InitializationError {
        this(new AllDefaultPossibilitiesBuilder(true), klass, suiteClasses);
}
AllDefaultPossibilitiesBuilder的职责就是为每个类生找到对应的Runner,感兴趣可以查看其runnerForClass方法,比较容易理解,这里就不再赘述。
 
Matcher验证
 
上面我们分析了用@Test标注的函数是如何被JUnit执行的,但单单有@Test标注是肯定不够的,既然是测试,我们肯定需要一定的手段来验证程序的的执行是符合预期的。JUnit提供了Matcher机制,可以满足我们大部分的需求。Matcher相关类主要在org.hamcrest包下,先来看下类图:
 
 
 
上图仅仅列出了org.hamcrest包下的一部分类,这些类一起组合起来形成了JUnit强大的验证机制。
 
验证的基本写法是:
 
MatcherAssert.assertThat("saymagic", CoreMatchers.containsString("magic"));
首先我们需要调用的是MatcherAssert的assertThat方法,这个方法最终辗转为:
 
 public static <T> void assertThat(String reason, T actual, Matcher<? super T> matcher) {
        if (!matcher.matches(actual)) {
            Description description = new StringDescription();
            description.appendText(reason)
                       .appendText("\nExpected: ")
                       .appendDescriptionOf(matcher)
                       .appendText("\n     but: ");
            matcher.describeMismatch(actual, description);
            throw new AssertionError(description.toString());
        }
}
这个函数目的很是明确,直接判断matcher是否匹配,不匹配则封装描述信息,然后抛出异常。所以我们来关注matcher的matchs方法都做了些什么,CoreMatchers.containsString("magic")返回的就是一个matcher, CoreMatchers相当于一个静态工厂,提供了大量的静态方法来返回各种Matcher:
 
 
 
我们就已刚刚的containsString为例,查看其内部代码:
 
 public static org.hamcrest.Matcher<java.lang.String> containsString(java.lang.String substring) {
    return org.hamcrest.core.StringContains.containsString(substring);
  }
可见其调用了StringContains的一个静态方法,继续追:
 
@Factory
public static Matcher<String> containsString(String substring) {
   return new StringContains(substring);
}
这里很简单,直接new了一个StringContains实例,StringContains的继承关系如下:
 
 
 
首先BaseMatcher实现了Matcher接口,TypeSafeMatcher是BaseMatcher的一个抽象实现,它的matches方法如下:
 
public final boolean matches(Object item) {
   return item != null
           && expectedType.isInstance(item)
           && matchesSafely((T) item);
}
可见它在验证前作了判空与类型的校验,所以子类就可以实现matchesSafely方法,就无需在此方法中进行判空与类型的验证了。
 
SubstringMatchers是TypeSafeMatcher的一种实现,它是对字符串类验证的一种抽象,它的matchesSafely方法如下:
 
@Override
public boolean matchesSafely(String item) {
    return evalSubstringOf(item);

原文转自:http://blog.saymagic.cn/2016/09/30/understand-Junit.html