Junit4.8.2 source code analysis-3 testclass and runnerbuilder

Source: Internet
Author: User

tag: junit4.8.2 Source Code

吃柿子专挑软的捏。JUnit4的核心是org.junit.runner.Runner,它涉及的类型太多,今天看几个简单的类型。看完了而且不准备回头再看的类型,yqj2065会在BlueJ中将它删除。删除如NullBuilder时,将import org.junit.internal.builders.NullBuilder加到本包的它的客户类中(其他包使用的,是BlueJ库中引入的包文件中的类),以保证整个项目可以编译和生成JavaDoc。

org.junit.runners.model.TestClass

JUnit4的输入,严格地说是一个或多个(组)单元测试类的Class对象。由于JDK中对标注的处理代价高昂,TestClass事先对单元测试类的标注相关的内容提取出来,1便于处理,2尽量共享。TestClass的3个成员变量

private final Class<?> fClass;
private Map<Class<?>, List<FrameworkMethod>> fMethodsForAnnotations= new HashMap<>();
private Map<Class<?>, List<FrameworkField>> fFieldsForAnnotations= new HashMap<>();

fClass是TestClass封装的单元测试类的Class对象。public Class<?> getJavaClass() 返回的就是它,而String getName()是它映射的单元测试类的类全名(或"null")。

fMethodsForAnnotations  每一种标识与被该标注修饰的方法的封装类的List即List<FrameworkMethod>的键值对。如果JUnit4设计一个标记接口JUnit4Annotation,其类型定义可以更小一些 如 Map<Class<? extends JUnit4Annotation>, List<FrameworkMethod> >。要是我,会这么做。

fFieldsForAnnotations 暂时不想看它,for Rules。

TestClass的构造器初始化3个成员变量。它要求单元测试类只能够有一个构造器。通过反射,构造器将单元测试类的所有祖先类放在一个List<Class<?>>中,找到它们每一个声明的方法,并按照方法的标注填入fMethodsForAnnotations和fFieldsForAnnotations。

而曝露出来的接口则是按照标注(key)获得Map中映射的List。

public List<FrameworkMethod> getAnnotatedMethods(Class<? extends Annotation> annotationClass) 

public List<FrameworkField> getAnnotatedFields(  Class<? extends Annotation> annotationClass) 

以及

public <T> List<T> getAnnotatedFieldValues(Object test,Class<? extends Annotation> annotationClass, Class<T> valueClass) 暂时忽略

public Annotation[] getAnnotations()

public Constructor<?> getOnlyConstructor()

TestClass的源代码比较容易看懂,目标清晰的代码都容易懂。

相关的类:FrameworkMethod、FrameworkField和它们的父类FrameworkMember<T>

FrameworkMethod

封装一个被标注的方法,标注为@Test 、@Before、@After、@BeforeClass、@AfterClass、@Ignore等。

以单元测试类TestUnit为例:

package myTest.TestClass;import myTest.HelloWorld;import static org.junit.Assert.*;import org.junit.Test;public class TestUnit{    public TestUnit(){    }    @Test    public void add(){        HelloWorld h = new HelloWorld();        assertEquals(5.0, h.add(1, 2), 0.1);    }    @Test    public void hello(){                assertEquals(5.0,4.0, 0.1);    }}
虽然可以直接运行测试各个@Test,我们还是编写demo程序,

package myTest.TestClass;import static tool.Print.*;import java.util.List;import java.lang.reflect.*;import org.junit.runners.model.*;import org.junit.Test;/** * org.junit.runners.model.FrameworkMethod * 封装一个被测试的方法 * @Test 、@Before、@After、@BeforeClass、@AfterClass、@Ignore */public class TestClassDemo{    public static void test()throws Throwable{        TestClass klass = new TestClass(TestUnit.class);        pln(klass.getName() );        List<FrameworkMethod> list = klass.getAnnotatedMethods(Test.class);        for(FrameworkMethod fm :list){            try {                fm.invokeExplosively((TestUnit)klass.getJavaClass().newInstance(), new Object[0]) ;            }catch (Throwable e) {                pln(e);            }finally{                pln(fm.getName()+" invoked!" );            }        }    }}
注意: invokeExplosively(final Object target, final Object... params)用于调用单元测试类的@Test方法,参数target为(TestUnit)klass.getJavaClass() .newInstance(),通常的测试方法的没有参数,取 new Object[0]

org.junit.runners.model.RunnerBuilder

单元测试类可能使用各种@Target(ElementType.TYPE)的标注如@Ignore、@RunWith、@SuiteClasse。org.junit.runners.model.RunnerBuilder针对这些标注产生不同的Runner。RunnerBuilder虽然取名builder,其实是工厂方法

public abstract Runner runnerForClass(Class<?>testClass) throws Throwable; //工厂方法

1. NullBuilder  如同定义数学的0一样。@Override Runner runnerForClass(Class<?>)返回null。删除

2. IgnoredBuilder  如果测试类由@Ignore标注,生成一个Runner子类IgnoredClassRunner对象。删除

3. AnnotatedBuilder  如果测试类由@RunWith标注,生成一个Runner对象。

4.兼容用JUnit3Builder   如果测试类使用JUnit3风格,生成一个Unit38ClassRunner对象。删除

5. JUnit4Builder  如果测试类使用JUnit4风格,生成一个BlockJUnit4ClassRunner对象。删除

6. SuiteMethodBuilder  组的问题保留

7. AllDefaultPossibilitiesBuilder 合集。按照IgnoredBuilder、AnnotatedBuilder、SuiteMethodBuilder(如果不使用组,则返回NullBuilder)、JUnit3Builder和JUnit4Builder的顺序创建各种RunnerBuilder,先调用RunnerBuilder.safeRunnerForClass方法再判断一个RunnerBuilder是否为null,非空则是AllDefaultPossibilitiesBuilder将使用的RunnerBuilder。



JUnit4.8.2源代码分析-3 TestClass 和RunnerBuilder

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.