All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kuali.rice.test.runners.LoadTimeWeavableTestRunner Maven / Gradle / Ivy

Go to download

This module contains rice's internal integration testing tools. This module is internal to rice and should not used outside of the rice project. It should only be depended on by rice integration test code. This module can depend on any part of rice.

There is a newer version: 2.6.2
Show newest version
/*
 * Copyright 2005-2014 The Kuali Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.opensource.org/licenses/ecl2.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.kuali.rice.test.runners;

import org.apache.commons.beanutils.MethodUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.runners.model.EachTestNotifier;
import org.junit.internal.runners.model.ReflectiveCallable;
import org.junit.internal.runners.statements.ExpectException;
import org.junit.internal.runners.statements.Fail;
import org.junit.internal.runners.statements.FailOnTimeout;
import org.junit.internal.runners.statements.InvokeMethod;
import org.junit.internal.runners.statements.RunAfters;
import org.junit.internal.runners.statements.RunBefores;
import org.junit.rules.RunRules;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
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.runner.notification.StoppedByUserException;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerScheduler;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;
import org.kuali.rice.core.api.util.ShadowingInstrumentableClassLoader;
import org.kuali.rice.test.MethodAware;

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

import static org.junit.internal.runners.rules.RuleMemberValidator.*;


/**
 * A JUnit test {@link org.junit.runner.Runner} which uses a custom classloader with a copy of the classpath and allows
 * for transformers to be added to the ClassLoader for load-time weaving.
 *
 * 

Useful when writing tests that use JPA with EclipseLink since it depends upon load-time weaving.

* *

In order to use this class, you must have a {@link BootstrapTest} annotation available somewhere in the hierarchy * of your test class (usually on the same class where the {@link RunWith} annotation is specified which references this * runner class). This informs the runner about a test that it can run to execute any one-time initialization for * the test suite. Ideally, this bootstrap test will execute code which loads JPA persistence units and any associated * ClassFileTransformers for load-time weaving. This is necessary because it is common for an integration test to have * references in the test class itself to JPA entities which need to be weaved. When this occurs, if the persistence * units and ClassFileTransformers are not properly loaded before the entity classes are loaded by the classloader, then * instrumentation will (silently!) fail to occur.

* *

Much of the code in this class was copied from the JUnit ParentRunner, BlockJUnit4ClassRunner, and * TomcatInstrumentableClassLoader.

* * @author Kuali Rice Team ([email protected]) */ public class LoadTimeWeavableTestRunner extends Runner implements Filterable, Sortable { private static final String[] JUNIT_CLASSLOADER_EXCLUDES = { "org.junit.", "junit.framework." }; private final TestClass originalTestClass; private TestClass fTestClass; private Method currentMethod; // static because we only need one custom loader per JVM in which the tests are running, otherwise the memory // usage gets crazy! private static ClassLoader customLoader; private Sorter fSorter = Sorter.NULL; private List originalFilteredChildren = null; private List filteredChildren = null; private static final ThreadLocal runningBootstrapTest = new ThreadLocal() { @Override protected Boolean initialValue() { return Boolean.FALSE; } }; private RunnerScheduler fScheduler = new RunnerScheduler() { public void schedule(Runnable childStatement) { childStatement.run(); } public void finished() { // do nothing } }; /** * Constructs a new {@code ParentRunner} that will run {@code @TestClass} */ public LoadTimeWeavableTestRunner(Class testClass) throws InitializationError { this.originalTestClass = new TestClass(testClass); if (LoadTimeWeavableTestRunner.customLoader == null) { LoadTimeWeavableTestRunner.customLoader = new ShadowingInstrumentableClassLoader(testClass.getClassLoader(), JUNIT_CLASSLOADER_EXCLUDES); } validate(); } private TestClass getCustomTestClass(Class originalTestClass, ClassLoader customLoader) { try { Class newTestClass = customLoader.loadClass(originalTestClass.getName()); if (newTestClass == originalTestClass) { throw new IllegalStateException(newTestClass.getName() + " loaded from custom class loader should have been a different instance but was the same!"); } return new TestClass(newTestClass); } catch (ClassNotFoundException e) { throw new IllegalStateException("Failed to load test class from custom classloader: " + originalTestClass.getName()); } } protected ClassLoader getCustomClassLoader() { return customLoader; } /** * Adds to {@code errors} if any method in this class is annotated with * {@code annotation}, but: *
    *
  • is not public, or *
  • takes parameters, or *
  • returns something other than void, or *
  • is static (given {@code isStatic is false}), or *
  • is not static (given {@code isStatic is true}). */ protected void validatePublicVoidNoArgMethods(Class annotation, boolean isStatic, List errors) { List methods = getOriginalTestClass().getAnnotatedMethods(annotation); for (FrameworkMethod eachTestMethod : methods) { eachTestMethod.validatePublicVoidNoArg(isStatic, errors); } } private void validateClassRules(List errors) { CLASS_RULE_VALIDATOR.validate(getOriginalTestClass(), errors); CLASS_RULE_METHOD_VALIDATOR.validate(getOriginalTestClass(), errors); } /** * Constructs a {@code Statement} to run all of the tests in the test class. Override to add pre-/post-processing. * Here is an outline of the implementation: *
      *
    • Call {@link #runChild(org.junit.runners.model.FrameworkMethod, org.junit.runner.notification.RunNotifier)} on each object returned by {@link #getChildren()} (subject to any imposed filter and sort).
    • *
    • ALWAYS run all non-overridden {@code @BeforeClass} methods on this class * and superclasses before the previous step; if any throws an * Exception, stop execution and pass the exception on. *
    • ALWAYS run all non-overridden {@code @AfterClass} methods on this class * and superclasses before any of the previous steps; all AfterClass methods are * always executed: exceptions thrown by previous steps are combined, if * necessary, with exceptions from AfterClass methods into a * {@link org.junit.runners.model.MultipleFailureException}. *
    * * @return {@code Statement} */ protected Statement classBlock(final RunNotifier notifier) { Statement statement = childrenInvoker(notifier); statement = withBeforeClasses(statement); statement = withAfterClasses(statement); statement = withClassRules(statement); return statement; } /** * Returns a {@link org.junit.runners.model.Statement}: run all non-overridden {@code @BeforeClass} methods on this class * and superclasses before executing {@code statement}; if any throws an * Exception, stop execution and pass the exception on. */ protected Statement withBeforeClasses(Statement statement) { List befores = getTestClass() .getAnnotatedMethods(BeforeClass.class); return befores.isEmpty() ? statement : new RunBefores(statement, befores, null); } /** * Returns a {@link org.junit.runners.model.Statement}: run all non-overridden {@code @AfterClass} methods on this class * and superclasses before executing {@code statement}; all AfterClass methods are * always executed: exceptions thrown by previous steps are combined, if * necessary, with exceptions from AfterClass methods into a * {@link org.junit.runners.model.MultipleFailureException}. */ protected Statement withAfterClasses(Statement statement) { List afters = getTestClass() .getAnnotatedMethods(AfterClass.class); return afters.isEmpty() ? statement : new RunAfters(statement, afters, null); } /** * Returns a {@link org.junit.runners.model.Statement}: apply all * static fields assignable to {@link org.junit.rules.TestRule} * annotated with {@link org.junit.ClassRule}. * * @param statement the base statement * @return a RunRules statement if any class-level {@link org.junit.Rule}s are * found, or the base statement */ private Statement withClassRules(Statement statement) { List classRules = classRules(); return classRules.isEmpty() ? statement : new RunRules(statement, classRules, getDescription()); } /** * @return the {@code ClassRule}s that can transform the block that runs * each method in the tested class. */ protected List classRules() { List result = getTestClass().getAnnotatedMethodValues(null, ClassRule.class, TestRule.class); result.addAll(getTestClass().getAnnotatedFieldValues(null, ClassRule.class, TestRule.class)); return result; } /** * Returns a {@link org.junit.runners.model.Statement}: Call {@link #runChild(org.junit.runners.model.FrameworkMethod, org.junit.runner.notification.RunNotifier)} * on each object returned by {@link #getChildren()} (subject to any imposed * filter and sort) */ protected Statement childrenInvoker(final RunNotifier notifier) { return new Statement() { @Override public void evaluate() { runChildren(notifier); } }; } private void runChildren(final RunNotifier notifier) { for (final FrameworkMethod each : getFilteredChildren()) { fScheduler.schedule(new Runnable() { public void run() { LoadTimeWeavableTestRunner.this.runChild(each, notifier); } }); } fScheduler.finished(); } /** * Returns a name used to describe this Runner */ protected String getName() { return getOriginalTestClass().getName(); } /** * Returns a {@link org.junit.runners.model.TestClass} object wrapping the class to be executed. */ public final TestClass getTestClass() { if (fTestClass == null) { throw new IllegalStateException("Attempted to access test class but it has not yet been initialized!"); } return fTestClass; } /** * Returns the original test class that was passed to this test runner. */ public final TestClass getOriginalTestClass() { return originalTestClass; } /** * Runs a {@link org.junit.runners.model.Statement} that represents a leaf (aka atomic) test. */ protected final void runLeaf(Statement statement, Description description, RunNotifier notifier) { EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description); eachNotifier.fireTestStarted(); try { statement.evaluate(); } catch (AssumptionViolatedException e) { eachNotifier.addFailedAssumption(e); } catch (Throwable e) { eachNotifier.addFailure(e); } finally { eachNotifier.fireTestFinished(); } } /** * @return the annotations that should be attached to this runner's * description. */ protected Annotation[] getRunnerAnnotations() { return getOriginalTestClass().getAnnotations(); } // // Implementation of Runner // @Override public Description getDescription() { Description description = Description.createSuiteDescription(getName(), getRunnerAnnotations()); for (FrameworkMethod child : getOriginalFilteredChildren()) { description.addChild(describeOriginalChild(child)); } return description; } @Override public void run(final RunNotifier notifier) { ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(customLoader); try { if (runBootstrapTest(notifier, getOriginalTestClass())) { this.fTestClass = getCustomTestClass(getOriginalTestClass().getJavaClass(), customLoader); EachTestNotifier testNotifier = new EachTestNotifier(notifier, getDescription()); try { Statement statement = classBlock(notifier); statement.evaluate(); } catch (AssumptionViolatedException e) { testNotifier.fireTestIgnored(); } catch (StoppedByUserException e) { throw e; } catch (Throwable e) { testNotifier.addFailure(e); } } } finally { Thread.currentThread().setContextClassLoader(currentContextClassLoader); } } protected boolean runBootstrapTest(RunNotifier notifier, TestClass testClass) { if (!runningBootstrapTest.get().booleanValue()) { runningBootstrapTest.set(Boolean.TRUE); try { BootstrapTest bootstrapTest = getBootstrapTestAnnotation(testClass.getJavaClass()); if (bootstrapTest != null) { Result result = JUnitCore.runClasses(bootstrapTest.value()); List failures = result.getFailures(); for (Failure failure : failures) { notifier.fireTestFailure(failure); } return result.getFailureCount() == 0; } else { throw new IllegalStateException("LoadTimeWeavableTestRunner, must be coupled with an @BootstrapTest annotation to define the bootstrap test to execute."); } } finally { runningBootstrapTest.set(Boolean.FALSE); } } return true; } private BootstrapTest getBootstrapTestAnnotation(Class testClass) { BootstrapTest bootstrapTest = testClass.getAnnotation(BootstrapTest.class); if (bootstrapTest != null) { return bootstrapTest; } else if (testClass.getSuperclass() != null) { return getBootstrapTestAnnotation(testClass.getSuperclass()); } else { return null; } } // // Implementation of Filterable and Sortable // public void filter(Filter filter) throws NoTestsRemainException { for (Iterator iter = getOriginalFilteredChildren().iterator(); iter.hasNext(); ) { FrameworkMethod each = iter.next(); if (shouldRun(filter, each)) { try { filter.apply(each); } catch (NoTestsRemainException e) { iter.remove(); } } else { iter.remove(); } } if (getOriginalFilteredChildren().isEmpty()) { throw new NoTestsRemainException(); } } public void sort(Sorter sorter) { fSorter = sorter; for (FrameworkMethod each : getOriginalFilteredChildren()) { sortChild(each); } Collections.sort(getOriginalFilteredChildren(), comparator()); } // // Private implementation // private void validate() throws InitializationError { List errors = new ArrayList(); collectInitializationErrors(errors); if (!errors.isEmpty()) { throw new InitializationError(errors); } } private List getOriginalFilteredChildren() { if (originalFilteredChildren == null) { originalFilteredChildren = new ArrayList(getOriginalChildren()); } return originalFilteredChildren; } private List getFilteredChildren() { if (getOriginalFilteredChildren() == null) { throw new IllegalStateException("Attempted to get filtered children before original filtered children were initialized."); } if (filteredChildren == null) { filteredChildren = new ArrayList(); List testMethods = computeTestMethods(); for (FrameworkMethod originalMethod : getOriginalFilteredChildren()) { for (FrameworkMethod testMethod : testMethods) { if (originalMethod.isShadowedBy(testMethod)) { filteredChildren.add(testMethod); } } } } return filteredChildren; } private void sortChild(FrameworkMethod child) { fSorter.apply(child); } private boolean shouldRun(Filter filter, FrameworkMethod each) { return filter.shouldRun(describeOriginalChild(each)); } private Comparator comparator() { return new Comparator() { public int compare(FrameworkMethod o1, FrameworkMethod o2) { return fSorter.compare(describeChild(o1), describeChild(o2)); } }; } // // Implementation of ParentRunner // /** * Runs the test corresponding to {@code child}, which can be assumed to be * an element of the list returned by {@link #getChildren()}. * Subclasses are responsible for making sure that relevant test events are * reported through {@code notifier} */ protected void runChild(final FrameworkMethod method, RunNotifier notifier) { this.currentMethod = method.getMethod(); try { Description description = describeChild(method); if (method.getAnnotation(Ignore.class) != null) { notifier.fireTestIgnored(description); } else { runLeaf(methodBlock(method), description, notifier); } } finally { this.currentMethod = null; } } /** * Returns a {@link org.junit.runner.Description} for {@code child}, which can be assumed to * be an element of the list returned by {@link #getChildren()} */ protected Description describeChild(FrameworkMethod method) { return Description.createTestDescription(getTestClass().getJavaClass(), testName(method), method.getAnnotations()); } protected Description describeOriginalChild(FrameworkMethod method) { return Description.createTestDescription(getOriginalTestClass().getJavaClass(), testName(method), method.getAnnotations()); } /** * Returns a list of objects that define the children of this Runner. */ protected List getChildren() { return computeTestMethods(); } protected List getOriginalChildren() { return computeOriginalTestMethods(); } // // Override in subclasses // /** * Returns the methods that run tests. Default implementation returns all * methods annotated with {@code @Test} on this class and superclasses that * are not overridden. */ protected List computeTestMethods() { return getTestClass().getAnnotatedMethods(Test.class); } protected List computeOriginalTestMethods() { return getOriginalTestClass().getAnnotatedMethods(Test.class); } /** * Adds to {@code errors} a throwable for each problem noted with the test class (available from {@link #getTestClass()}). * Default implementation adds an error for each method annotated with * {@code @BeforeClass} or {@code @AfterClass} that is not * {@code public static void} with no arguments. */ protected void collectInitializationErrors(List errors) { validatePublicVoidNoArgMethods(BeforeClass.class, true, errors); validatePublicVoidNoArgMethods(AfterClass.class, true, errors); validateClassRules(errors); validateNoNonStaticInnerClass(errors); validateConstructor(errors); validateInstanceMethods(errors); validateFields(errors); validateMethods(errors); } protected void validateNoNonStaticInnerClass(List errors) { if (getOriginalTestClass().isANonStaticInnerClass()) { String gripe = "The inner class " + getOriginalTestClass().getName() + " is not static."; errors.add(new Exception(gripe)); } } /** * Adds to {@code errors} if the test class has more than one constructor, * or if the constructor takes parameters. Override if a subclass requires * different validation rules. */ protected void validateConstructor(List errors) { validateOnlyOneConstructor(errors); validateZeroArgConstructor(errors); } /** * Adds to {@code errors} if the test class has more than one constructor * (do not override) */ protected void validateOnlyOneConstructor(List errors) { if (!hasOneConstructor()) { String gripe = "Test class should have exactly one public constructor"; errors.add(new Exception(gripe)); } } /** * Adds to {@code errors} if the test class's single constructor takes * parameters (do not override) */ protected void validateZeroArgConstructor(List errors) { if (!getOriginalTestClass().isANonStaticInnerClass() && hasOneConstructor() && (getOriginalTestClass().getOnlyConstructor().getParameterTypes().length != 0)) { String gripe = "Test class should have exactly one public zero-argument constructor"; errors.add(new Exception(gripe)); } } private boolean hasOneConstructor() { return getOriginalTestClass().getJavaClass().getConstructors().length == 1; } /** * Adds to {@code errors} for each method annotated with {@code @Test}, * {@code @Before}, or {@code @After} that is not a public, void instance * method with no arguments. * * @deprecated unused API, will go away in future version */ @Deprecated protected void validateInstanceMethods(List errors) { validatePublicVoidNoArgMethods(After.class, false, errors); validatePublicVoidNoArgMethods(Before.class, false, errors); validateTestMethods(errors); if (computeOriginalTestMethods().size() == 0) { errors.add(new Exception("No runnable methods")); } } protected void validateFields(List errors) { RULE_VALIDATOR.validate(getOriginalTestClass(), errors); } private void validateMethods(List errors) { RULE_METHOD_VALIDATOR.validate(getOriginalTestClass(), errors); } /** * Adds to {@code errors} for each method annotated with {@code @Test}that * is not a public, void instance method with no arguments. */ protected void validateTestMethods(List errors) { validatePublicVoidNoArgMethods(Test.class, false, errors); } /** * Returns a new fixture for running a test. Default implementation executes * the test class's no-argument constructor (validation should have ensured * one exists). */ protected Object createTest() throws Exception { Object test = getTestClass().getOnlyConstructor().newInstance(); setTestName(test, currentMethod); setTestMethod(test, currentMethod); return test; } /** * Sets the {@link java.lang.reflect.Method} on the test case if it is {@link org.kuali.rice.test.MethodAware} * @param method the current method to be run * @param test the test instance */ protected void setTestMethod(Object test, Method method) throws Exception { Class methodAwareClass = Class.forName(MethodAware.class.getName(), true, getCustomClassLoader()); if (methodAwareClass.isInstance(test)) { Method setTestMethod = methodAwareClass.getMethod("setTestMethod", Method.class); setTestMethod.invoke(test, method); } } protected void setTestName(final Object test, final Method testMethod) throws Exception { String name = testMethod == null ? "" : testMethod.getName(); final Method setNameMethod = MethodUtils.getAccessibleMethod(test.getClass(), "setName", new Class[]{String.class}); if (setNameMethod != null) { setNameMethod.invoke(test, name); } } /** * Returns the name that describes {@code method} for {@link org.junit.runner.Description}s. * Default implementation is the method's name */ protected String testName(FrameworkMethod method) { return method.getName(); } /** * Returns a Statement that, when executed, either returns normally if * {@code method} passes, or throws an exception if {@code method} fails. * * Here is an outline of the default implementation: * *
      *
    • Invoke {@code method} on the result of {@code createTest()}, and * throw any exceptions thrown by either operation. *
    • HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code * expecting} attribute, return normally only if the previous step threw an * exception of the correct type, and throw an exception otherwise. *
    • HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code * timeout} attribute, throw an exception if the previous step takes more * than the specified number of milliseconds. *
    • ALWAYS run all non-overridden {@code @Before} methods on this class * and superclasses before any of the previous steps; if any throws an * Exception, stop execution and pass the exception on. *
    • ALWAYS run all non-overridden {@code @After} methods on this class * and superclasses after any of the previous steps; all After methods are * always executed: exceptions thrown by previous steps are combined, if * necessary, with exceptions from After methods into a * {@link org.junit.runners.model.MultipleFailureException}. *
    • ALWAYS allow {@code @Rule} fields to modify the execution of the * above steps. A {@code Rule} may prevent all execution of the above steps, * or add additional behavior before and after, or modify thrown exceptions. * For more information, see {@link org.junit.rules.TestRule} *
    * * This can be overridden in subclasses, either by overriding this method, * or the implementations creating each sub-statement. */ protected Statement methodBlock(FrameworkMethod method) { Object test; try { test = new ReflectiveCallable() { @Override protected Object runReflectiveCall() throws Throwable { return createTest(); } }.run(); } catch (Throwable e) { return new Fail(e); } Statement statement = methodInvoker(method, test); statement = possiblyExpectingExceptions(method, test, statement); statement = withPotentialTimeout(method, test, statement); statement = withBefores(method, test, statement); statement = withAfters(method, test, statement); statement = withRules(method, test, statement); return statement; } // // Statement builders // /** * Returns a {@link org.junit.runners.model.Statement} that invokes {@code method} on {@code test} */ protected Statement methodInvoker(FrameworkMethod method, Object test) { return new InvokeMethod(method, test); } /** * Returns a {@link org.junit.runners.model.Statement}: if {@code method}'s {@code @Test} annotation * has the {@code expecting} attribute, return normally only if {@code next} * throws an exception of the correct type, and throw an exception * otherwise. * * @deprecated Will be private soon: use Rules instead */ @Deprecated protected Statement possiblyExpectingExceptions(FrameworkMethod method, Object test, Statement next) { Test annotation = method.getAnnotation(Test.class); return expectsException(annotation) ? new ExpectException(next, getExpectedException(annotation)) : next; } /** * Returns a {@link org.junit.runners.model.Statement}: if {@code method}'s {@code @Test} annotation * has the {@code timeout} attribute, throw an exception if {@code next} * takes more than the specified number of milliseconds. * * @deprecated Will be private soon: use Rules instead */ @Deprecated protected Statement withPotentialTimeout(FrameworkMethod method, Object test, Statement next) { long timeout = getTimeout(method.getAnnotation(Test.class)); return timeout > 0 ? new FailOnTimeout(next, timeout) : next; } /** * Returns a {@link org.junit.runners.model.Statement}: run all non-overridden {@code @Before} * methods on this class and superclasses before running {@code next}; if * any throws an Exception, stop execution and pass the exception on. * * @deprecated Will be private soon: use Rules instead */ @Deprecated protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) { List befores = getTestClass().getAnnotatedMethods(Before.class); return befores.isEmpty() ? statement : new RunBefores(statement, befores, target); } /** * Returns a {@link org.junit.runners.model.Statement}: run all non-overridden {@code @After} * methods on this class and superclasses before running {@code next}; all * After methods are always executed: exceptions thrown by previous steps * are combined, if necessary, with exceptions from After methods into a * {@link org.junit.runners.model.MultipleFailureException}. * * @deprecated Will be private soon: use Rules instead */ @Deprecated protected Statement withAfters(FrameworkMethod method, Object target, Statement statement) { List afters = getTestClass().getAnnotatedMethods( After.class); return afters.isEmpty() ? statement : new RunAfters(statement, afters, target); } private Statement withRules(FrameworkMethod method, Object target, Statement statement) { List testRules = getTestRules(target); Statement result = statement; result = withMethodRules(method, testRules, target, result); result = withTestRules(method, testRules, result); return result; } private Statement withMethodRules(FrameworkMethod method, List testRules, Object target, Statement result) { for (org.junit.rules.MethodRule each : getMethodRules(target)) { if (!testRules.contains(each)) { result = each.apply(result, method, target); } } return result; } private List getMethodRules(Object target) { return rules(target); } /** * @param target the test case instance * @return a list of MethodRules that should be applied when executing this * test */ protected List rules(Object target) { return getTestClass().getAnnotatedFieldValues(target, Rule.class, org.junit.rules.MethodRule.class); } /** * Returns a {@link org.junit.runners.model.Statement}: apply all non-static value fields * annotated with {@link org.junit.Rule}. * * @param statement The base statement * @return a RunRules statement if any class-level {@link org.junit.Rule}s are * found, or the base statement */ private Statement withTestRules(FrameworkMethod method, List testRules, Statement statement) { return testRules.isEmpty() ? statement : new RunRules(statement, testRules, describeChild(method)); } /** * @param target the test case instance * @return a list of TestRules that should be applied when executing this * test */ protected List getTestRules(Object target) { List result = getTestClass().getAnnotatedMethodValues(target, Rule.class, TestRule.class); result.addAll(getTestClass().getAnnotatedFieldValues(target, Rule.class, TestRule.class)); return result; } private Class getExpectedException(Test annotation) { if (annotation == null || annotation.expected() == Test.None.class) { return null; } else { return annotation.expected(); } } private boolean expectsException(Test annotation) { return getExpectedException(annotation) != null; } private long getTimeout(Test annotation) { if (annotation == null) { return 0; } return annotation.timeout(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy