全国城市切换

关于Junit的 源码解析

作者:郑州知网 日期:2020-07-15 人气:8427



junit4 下的所有的testcase都是在Runner下执行的, 可以将Runner理解为junit运行的容器, 默认情况下junit会使用JUnit4ClassRunner作为所有testcase的执行容器。

如果要定制自己的junit, 则可以实现自己的Runner,最简单的办法就是Junit4ClassRunner继承, spring-test, unitils这些框架就是采用这样的做法。

如在spring中是SpringJUnit4ClassRunner, 在unitils中是UnitilsJUnit4TestClassRunner, 一般我们的testcase都是在通过eclipse插件来执行的, eclipse的junit插件会在执行的时候会初始化指定的Runner。初始化的过程可以在ClassRequest中找到。


package org.junit.internal.runners;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.Filterable;
import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runner.manipulation.Sortable;
import org.junit.runner.manipulation.Sorter;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;

/**
 * @deprecated Included for backwards compatibility with JUnit 4.4. Will be
 *             removed in the next release. Please use
 *             {@link BlockJUnit4ClassRunner} in place of
 *             {@link JUnit4ClassRunner}.
 * 
 *             This may disappear as soon as 1 April 2009
 */
@Deprecated
public class JUnit4ClassRunner extends Runner implements Filterable, Sortable
{
    private final ListfTestMethods;

    private TestClass fTestClass;
	
    //将要测试的TestCase实例Class对象传入
    public JUnit4ClassRunner(Class klass) throws InitializationError
    {
        fTestClass = new TestClass(klass);
        fTestMethods = getTestMethods();
        //对要进行测试的方法展开验证
        validate();
    }
    
    //获取@test的方法List
    protected ListgetTestMethods()
    {
        return fTestClass.getTestMethods();
    }
	
    //对要进行测试的方法展开验证
    protected void validate() throws InitializationError
    {
        MethodValidator methodValidator = new MethodValidator(fTestClass);
        ();
        ();
    }

    @Override
    public void run(final RunNotifier notifier)
    {
        new ClassRoadie(notifier, fTestClass, getDescription(), new Runnable()
        {
            public void run()
            {
                runMethods(notifier);
            }
        }).runProtected();
    }

    protected void runMethods(final RunNotifier notifier)
    {
        for (Method method : fTestMethods)
            invokeTestMethod(method, notifier);
    }

    @Override
    public Description getDescription()
    {
        Description spec = (getName(), classAnnotations());
        ListtestMethods = fTestMethods;
        for (Method method : testMethods)
            (methodDescription(method));
        return spec;
    }

    protected Annotation[] classAnnotations()
    {
        return fTestClass.getJavaClass().getAnnotations();
    }

    protected String getName()
    {
        return getTestClass().getName();
    }

    protected Object createTest() throws Exception
    {
        return getTestClass().getConstructor().newInstance();
    }

    protected void invokeTestMethod(Method method, RunNotifier notifier)
    {
        Description description = methodDescription(method);
        Object test;
        try
        {
            test = createTest();
        }
        catch(InvocationTargetException e)
        {
            testAborted(notifier, description, ());
            return;
        }
        catch(Exception e)
        {
            testAborted(notifier, description, e);
            return;
        }
        TestMethod testMethod = wrapMethod(method);
        new MethodRoadie(test, testMethod, notifier, description).run();
    }

    private void testAborted(RunNotifier notifier, Description description, Throwable e)
    {
        (description);
        (new Failure(description, e));
        (description);
    }

    protected TestMethod wrapMethod(Method method)
    {
        return new TestMethod(method, fTestClass);
    }

    protected String testName(Method method)
    {
        return method.getName();
    }

    protected Description methodDescription(Method method)
    {
        return Description.createTestDescription(getTestClass().getJavaClass(), testName(method), testAnnotations(method));
    }

    protected Annotation[] testAnnotations(Method method)
    {
        return method.getAnnotations();
    }

    public void filter(Filter filter) throws NoTestsRemainException
    {
        for (Iteratoriter = (); ();)
        {
            Method method = ();
            if (!(methodDescription(method)))
                ();
        }
        if (())
            throw new NoTestsRemainException();
    }

    public void sort(final Sorter sorter)
    {
        (fTestMethods, new Comparator()
        {
            public int compare(Method o1, Method o2)
            {
                return sorter.compare(methodDescription(o1), methodDescription(o2));
            }
        });
    }

    protected TestClass getTestClass()
    {
        return fTestClass;
    }
}

不同于上一节提到的类

package org.junit.internal.runners;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runners.BlockJUnit4ClassRunner;

/**
 * @deprecated Included for backwards compatibility with JUnit 4.4. Will be
 *             removed in the next release. Please use
 *             {@link BlockJUnit4ClassRunner} in place of
 *             {@link JUnit4ClassRunner}.
 */
@Deprecated
public class TestClass
{
    private final Class fClass;

    public TestClass(Class klass)
    {
        fClass = klass;
    }

    public ListgetTestMethods()
    {
        return getAnnotatedMethods();
    }

    ListgetBefores()
    {
        return getAnnotatedMethods();
    }

    ListgetAfters()
    {
        return getAnnotatedMethods();
    }

    public ListgetAnnotatedMethods(Class annotationClass)
    {
        Listresults = new ArrayList();
        for (Class eachClass : getSuperClasses(fClass))
        {
            Method[] methods = ();
            for (Method eachMethod : methods)
            {
                Annotation annotation = (annotationClass);
                if (annotation != null && !isShadowed(eachMethod, results))
                    (eachMethod);
            }
        }
        if (runsTopToBottom(annotationClass))
            (results);
        return results;
    }

    private boolean runsTopToBottom(Class annotation)
    {
        return () || ();
    }

    private boolean isShadowed(Method method, Listresults)
    {
        for (Method each : results)
        {
            if (isShadowed(method, each))
                return true;
        }
        return false;
    }

    private boolean isShadowed(Method current, Method previous)
    {
        if (!().equals(()))
            return false;
        if (().length != ().length)
            return false;
        for (int i = 0; i < ().length; i++)
        {
            if (!()[i].equals(()[i]))
                return false;
        }
        return true;
    }

    private List<Class> getSuperClasses(Class testClass)
    {
        ArrayList<Class> results = new ArrayList<Class>();
        Class current = testClass;
        while (current != null)
        {
            (current);
            current = ();
        }
        return results;
    }

    public Constructor getConstructor() throws SecurityException, NoSuchMethodException
    {
        return fClass.getConstructor();
    }

    public Class getJavaClass()
    {
        return fClass;
    }

    public String getName()
    {
        return fClass.getName();
    }

}

用于在 类当中进行方法验证

package org.junit.internal.runners;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runners.BlockJUnit4ClassRunner;

/**
 * @deprecated Included for backwards compatibility with JUnit 4.4. Will be
 *             removed in the next release. Please use
 *             {@link BlockJUnit4ClassRunner} in place of {@link JUnit4ClassRunner}.
 */
@Deprecated
public class MethodValidator {

	private final ListfErrors= new ArrayList();

	private TestClass fTestClass;
    
	//类中
	//validate()方法中调用该构造函数-----第一步
	public MethodValidator(TestClass testClass) {
		fTestClass = testClass;
	}

	public void validateInstanceMethods() {
		validateTestMethods(After.class, false);
		validateTestMethods(, false);
		validateTestMethods(, false);
		
		Listmethods= ();
		if (() == 0)
			(new Exception("No runnable methods"));
	}

	public void validateStaticMethods() {
		validateTestMethods(, true);
		validateTestMethods(, true);
	}
	
	//Junit4ClassRunner类中调用第二步
	public ListvalidateMethodsForDefaultRunner() {
		//校验无参构造方法
		validateNoArgConstructor();
		//校验注解方法
		validateStaticMethods();
		validateInstanceMethods();
		return fErrors;
	}
	
	//Junit4ClassRunner类中第三步
	public void assertValid() throws InitializationError {
		if (!())
			throw new InitializationError(fErrors);
	}

	public void validateNoArgConstructor() {
		try {
			();
		} catch (Exception e) {
			(new Exception("Test class should have public zero-argument constructor", e));
		}
	}
	
    //校验要测试的方法 是否静态方法、是否public方法、是否返回值void、是否无参数
	//@param annotation 要测试的annotation类  
	//@param isStatic 是否要求静态方法
	private void validateTestMethods(Class annotation,boolean isStatic) {
		Listmethods= (annotation);
		
		for (Method each : methods) {
			if ((()) != isStatic) {
				String state= isStatic ? "should" : "should not";
				(new Exception("Method " + () + "() "
						+ state + " be static"));
			}
			if (!(().getModifiers()))
				(new Exception("Class " + ().getName()
						+ " should be public"));
			if (!(()))
				(new Exception("Method " + ()
						+ " should be public"));
			if (() != )
				(new Exception("Method " + ()
						+ " should be void"));
			if (().length != 0)
				(new Exception("Method " + ()
						+ " should have no parameters"));
		}
	}
}


你觉得这篇文章怎么样?

00

快捷导航

国内分销 直销是怎么来的 直销怎么能做好 海外分销系统 微分销管理系统 三级分销小程序 分销商城怎么样 直销公司做 阿里分销条件 分销怎么做小程序 双轨制直销软件开发 ectouch分销 数码产品分销 微店怎样做分销 直销有几种奖金制度 分销平台软件哪个好 专业直销软件 产品直销软件 中国合法直销有哪些 微信分销 网上直销平台 农产品分销 直销产品的排名 完美产品直销 直销软件开发哪里好 什么是微分销 直销是什么啊 直销模式有产品 1688怎么分销 直销公司的产品