根据上一篇blog,看到日志1流程:
surefire.ForkedBooter -> ForkedBooter.runSuitesInProcess
-> ForkedBooter.invokeProviderInSameClassLoader-> surefire.junit4.JUnit4Provider.invoke -> executeTestSet -> executeWithRerun
-> execute
-> junit.runners.ParentRunner.run -> evaluate -> runChildren -> schedule -> run
-> BlockJUnit4ClassRunner.runChild
-> junit.runners.ParentRunner.runLeaf
-> junit.rules.RunRules.evaluate
-> org.junit.internal.runners.statements.RunBefores.evaluate
-> junit.runners.model.FrameworkMethod.invokeExplosively
-> junit.internal.runners.model.ReflectiveCallable.run
-> junit.runners.model.FrameworkMethod.runReflectiveCall
这是 一个junit的版本调用过程,不同junit 版本,调用类不同,如日志2
-> ForkedBooter.invokeProviderInSameClassLoader
-> surefire.junit4.JUnit4Provider.invoke -> executeTestSet -> executeWithRerun
-> execute
-> junit.runners.ParentRunner.run -> evaluate -> runChildren -> schedule -> run
-> BlockJUnit4ClassRunner.runChild
-> org.junit.internal.runners.statements.InvokeMethod.evaluate
-> org.junit.runners.model.FrameworkMethod.invokeExplosively
-> org.junit.internal.runners.model.ReflectiveCallable.run
-> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall
InvokeMethod 了类代码:
public class InvokeMethod extends Statement {
private final FrameworkMethod fTestMethod;
private Object fTarget;
public InvokeMethod(FrameworkMethod testMethod, Object target) {
fTestMethod= testMethod;
fTarget= target;
}
@Override
public void evaluate() throws Throwable {
fTestMethod.invokeExplosively(fTarget);
}
Statement:
public abstract class Statement {
/**
* Run the action, throwing a {@code Throwable} if anything goes wrong.
*/
public abstract void evaluate() throws Throwable;
}FrameworkMethod代码:
public class FrameworkMethod {
private final Method fMethod;
/**
* Returns a new {@code FrameworkMethod} for {@code method}
*/
public FrameworkMethod(Method method) {
fMethod= method;
}
/**
* Returns the underlying Java method
*/
public Method getMethod() {
return fMethod;
}
/**
* Returns the result of invoking this method on {@code target} with
* parameters {@code params}. {@link InvocationTargetException}s thrown are
* unwrapped, and their causes rethrown.
*/
public Object invokeExplosively(final Object target, final Object... params)
throws Throwable {
return new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return fMethod.invoke(target, params);
}
}.run();
}
/**
* Returns the method's name
*/
public String getName() {
return fMethod.getName();
}
/**
* Adds to {@code errors} if this method:
* <ul>
* <li>is not public, or
* <li>takes parameters, or
* <li>returns something other than void, or
* <li>is static (given {@code isStatic is false}), or
* <li>is not static (given {@code isStatic is true}).
*/
public void validatePublicVoidNoArg(boolean isStatic, List<Throwable> errors) {
validatePublicVoid(isStatic, errors);
if (fMethod.getParameterTypes().length != 0)
errors.add(new Exception("Method " + fMethod.getName() + " should have no parameters"));
}
/**
* Adds to {@code errors} if this method:
* <ul>
* <li>is not public, or
* <li>returns something other than void, or
* <li>is static (given {@code isStatic is false}), or
* <li>is not static (given {@code isStatic is true}).
*/
public void validatePublicVoid(boolean isStatic, List<Throwable> errors) {
if (Modifier.isStatic(fMethod.getModifiers()) != isStatic) {
String state= isStatic ? "should" : "should not";
errors.add(new Exception("Method " + fMethod.getName() + "() " + state + " be static"));
}
if (!Modifier.isPublic(fMethod.getDeclaringClass().getModifiers()))
errors.add(new Exception("Class " + fMethod.getDeclaringClass().getName() + " should be public"));
if (!Modifier.isPublic(fMethod.getModifiers()))
errors.add(new Exception("Method " + fMethod.getName() + "() should be public"));
if (fMethod.getReturnType() != Void.TYPE)
errors.add(new Exception("Method " + fMethod.getName() + "() should be void"));
}
boolean isShadowedBy(List<FrameworkMethod> results) {
for (FrameworkMethod each : results)
if (isShadowedBy(each))
return true;
return false;
}
private boolean isShadowedBy(FrameworkMethod each) {
if (!each.getName().equals(getName()))
return false;
if (each.getParameterTypes().length != getParameterTypes().length)
return false;
for (int i= 0; i < each.getParameterTypes().length; i++)
if (!each.getParameterTypes()[i].equals(getParameterTypes()[i]))
return false;
return true;
}
@Override
public boolean equals(Object obj) {
if (!FrameworkMethod.class.isInstance(obj))
return false;
return ((FrameworkMethod) obj).fMethod.equals(fMethod);
}
@Override
public int hashCode() {
return fMethod.hashCode();
}
/**
* Returns true iff this is a no-arg method that returns a value assignable
* to {@code type}
*/
public boolean producesType(Class<?> type) {
return getParameterTypes().length == 0
&& type.isAssignableFrom(fMethod.getReturnType());
}
private Class<?>[] getParameterTypes() {
return fMethod.getParameterTypes();
}
/**
* Returns the annotations on this method
*/
public Annotation[] getAnnotations() {
return fMethod.getAnnotations();
}
/**
* Returns the annotation of type {@code annotationType} on this method, if
* one exists.
*/
public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
return fMethod.getAnnotation(annotationType);
}
}ReflectiveCallable类:public abstract class ReflectiveCallable {
public Object run() throws Throwable {
try {
return runReflectiveCall();
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
protected abstract Object runReflectiveCall() throws Throwable;
}
本文详细解析了JUnit测试执行的具体流程,从ForkedBooter的启动到BlockJUnit4ClassRunner运行子类的过程,深入探讨了不同JUnit版本间的调用差异,并通过具体的类代码示例解释了关键步骤。
1899

被折叠的 条评论
为什么被折叠?



