package de.bechte.junit.runners.context.statements.builder;
import de.bechte.junit.runners.model.TestClassPool;
import org.junit.Before;
import org.junit.internal.runners.statements.Fail;
import org.junit.internal.runners.statements.RunBefores;
import org.junit.runner.Description;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;
import java.util.List;
import static de.bechte.junit.runners.util.ReflectionUtil.getEnclosingInstance;
/**
* The {@link HierarchicalRunBeforeStatementBuilder} creates a {@link RunBefores} statement for each context hierarchy
* level that evaluates all {@code @Before} annotated methods on that level. If no such method exist one (or even all)
* hierarchy levels is skipped and the builder returns the current (or provided) next {@link Statement}.
*/
public class HierarchicalRunBeforeStatementBuilder implements MethodStatementBuilder {
public Statement createStatement(final TestClass testClass, final FrameworkMethod method, final Object target,
final Statement next, final Description description, final RunNotifier notifier) {
Statement statement = next;
try {
for (Object instance = target; instance != null; instance = getEnclosingInstance(instance)) {
final TestClass instanceTestClass = TestClassPool.forClass(instance.getClass());
final List<FrameworkMethod> beforeMethods = instanceTestClass.getAnnotatedMethods(Before.class);
statement = beforeMethods.isEmpty() ? statement : new RunBefores(statement, beforeMethods, instance);
}
} catch (final IllegalAccessException e) {
statement = new Fail(e);
}
return statement;
}
}