JUnit源码解析(3)

发表于:2016-10-04来源:saymagic作者:saymagic点击数: 标签:junit
} }); } } finally { currentScheduler.finished(); } } 这个函数就体现了抽象的重要性,注意泛型T,它在ParentRunner的每个实现类中各不相同,在BlockJUnit4ClassRunner中T表示
                    }
               });
         }
     } finally {
         currentScheduler.finished();
     }
}
这个函数就体现了抽象的重要性,注意泛型T,它在ParentRunner的每个实现类中各不相同,在BlockJUnit4ClassRunner中T表示FrameworkMethod,具体到这个函数来讲getFilteredChildren拿到的是被@Test注解标注的FrameworkMethod,而在Suite中,T为Runner,而ParentRunner.this.runChild(each, notifier);这句的中的runChild(each, notifier)方法依旧是个抽象方法,我们先看BlockJUnit4ClassRunner中的实现:
 
@Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
     Description description = describeChild(method);
     if (isIgnored(method)) {
         notifier.fireTestIgnored(description);
     } else {
         runLeaf(methodBlock(method), description, notifier);
     }
}
isIgnored方法判断了method方法是否被@Ignore注解标识,如果是的话则直接通知notifier触发ignored事件,否则,执行runLeaf方法, runLeaf的第一个参数是Statement,所以,BlockJUnit4ClassRunner通过methodBlock方法将method转换为Statement:
 
protected Statement methodBlock(FrameworkMethod method) {
        Object test;
        try {
            test = new ReflectiveCallable() {
                @Override
                protected Object runReflectiveCall() throws Throwable {
                    return createTest();
                }
            }.run();
        } catch (Throwable e) {
            return new Fail(e);
        }
        Statement statement = methodInvoker(method, test);
        statement = possiblyExpectingExceptions(method, test, statement);
        statement = withPotentialTimeout(method, test, statement);
        statement = withBefores(method, test, statement);
        statement = withAfters(method, test, statement);
        statement = withRules(method, test, statement);
        return statement;
 }
前面的几行代码是在生成test 对象,而test对象的类型则是我们待测试的class,接下来追进methodInvoker方法:
 
protected Statement methodInvoker(FrameworkMethod method, Object test) {
        return new InvokeMethod(method, test);
}
可见,我们生成的Statement实例为InvokeMethod,我们看下其evaluate方法:
 
testMethod.invokeExplosively(target);
invokeExplosively函数做的事情就是对target对象调用testMethod方法。而前面我们说过,这个testMethod在BlockJUnit4ClassRunner中就是被@Test所标注的方法,此时,我们终于找到了@Test方法是在哪里被调用的了。别急,我们接着刚才的函数继续分析:
 
statement = possiblyExpectingExceptions(method, test, statement);
statement = withPotentialTimeout(method, test, statement);
statement = withBefores(method, test, statement);
statement = withAfters(method, test, statement);
statement = withRules(method, test, statement);
我们可以看到,statement不断的在变形,而通过withBefores,withRules这些函数的名字我们可以很容易猜到,这里就是在处理@Before,@Rule等注解的地方,我们以withBefores为例:
 
protected Statement withBefores(FrameworkMethod method, Object target,
            Statement statement) {
        List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
                Before.class);

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