package org.test4j.junit;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.test4j.junit.annotations.DataFrom;
import org.test4j.junit.parametermethod.FrameworkMethodWithParameters;
import org.test4j.junit.parametermethod.ParameterDataFromHelper;
import org.test4j.junit.statement.MethodAroundStatement;
import org.test4j.junit.statement.TestAroundStatement;
import org.test4j.module.core.CoreModule;
import org.test4j.module.core.TestContext;
import org.test4j.module.core.TestListener;
import org.test4j.module.core.ClazzAroundObject.ClazzBeforeObject;
import org.test4j.tools.commons.MethodHelper;
@SuppressWarnings({ "rawtypes" })
public class Test4JRunner extends BlockJUnit4ClassRunner {
static {
CoreModule.initSingletonInstance();
}
private Object testedObject = null;
private final Class testClazz;
private RuntimeException error;
/**
* Creates a test runner that runs all test methods in the given class.
*
* @param testClass the class, not null
* @throws org.junit.runners.model.InitializationError
* @throws InitializationError
*/
public Test4JRunner(Class testClass) throws InitializationError {
super(testClass);
this.testClazz = testClass;
TestContext.setContext(new ClazzBeforeObject(testClazz), null);
}
@Override
protected Object createTest() throws Exception {
if (this.testedObject == null) {
this.testedObject = this.getTestedObject();
}
return this.testedObject;
}
private Object getTestedObject() throws Exception {
this.error = null;
try {
Object tested = super.createTest();
return tested;
} catch (Exception e) {
e.printStackTrace();
this.error = new RuntimeException(e.getMessage(), e);
throw e;
}
}
private void initTestedObject() {
try {
this.testedObject = super.createTest();
TestContext.setContext(this.testedObject, null);
} catch (Throwable e) {
e.printStackTrace();
this.error = new RuntimeException(e.getMessage(), e);
}
}
@Override
protected Statement childrenInvoker(final RunNotifier notifier) {
return new Statement() {
@Override
public void evaluate() {
initTestedObject();
Test4JRunner.this.getTestListener().beforeClass(Test4JRunner.this.testClazz);
MethodHelper.invokeUnThrow(Test4JRunner.this, "runChildren", notifier);
Test4JRunner.this.getTestListener().afterClass(Test4JRunner.this.testedObject);
}
};
}
@Override
protected Statement methodBlock(FrameworkMethod method) {
Statement statement = super.methodBlock(method);
if (this.error != null) {
throw error;
}
statement = new TestAroundStatement(statement, getTestListener(), testedObject, method.getMethod());
return statement;
}
@Override
public Statement methodInvoker(FrameworkMethod method, Object test) {
Statement statement = super.methodInvoker(method, test);
statement = new MethodAroundStatement(statement, getTestListener(), test, method.getMethod());
return statement;
}
@Override
protected String testName(FrameworkMethod method) {
if (method instanceof FrameworkMethodWithParameters) {
return method.toString();
} else {
return super.testName(method);
}
}
private List<FrameworkMethod> testMethods;
/**
* {@inheritDoc}<br>
* 构造有参和无参的测试方法列表
*/
@Override
protected List<FrameworkMethod> computeTestMethods() {
Class testclazz = getTestClass().getJavaClass();
if (this.testMethods == null) {
List<FrameworkMethod> initTestMethods = super.computeTestMethods();
testMethods = new ArrayList<FrameworkMethod>();
for (FrameworkMethod frameworkMethod : initTestMethods) {
Method testMethod = frameworkMethod.getMethod();
testMethod.getDeclaringClass();
DataFrom dataFrom = testMethod.getAnnotation(DataFrom.class);
if (dataFrom == null) {
testMethods.add(frameworkMethod);
} else {
List<FrameworkMethodWithParameters> parameterizedTestMethods = ParameterDataFromHelper
.computeParameterizedTestMethods(testclazz, frameworkMethod.getMethod(), dataFrom);
testMethods.addAll(parameterizedTestMethods);
}
}
}
return this.testMethods;
}
/**
* @return The test listener
*/
protected TestListener getTestListener() {
return CoreModule.getTestListener();
}
}