Home | History | Annotate | Download | only in junit3
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package libcore.junit.junit3;
     17 
     18 import java.lang.annotation.Annotation;
     19 import java.lang.reflect.Method;
     20 import java.util.ArrayList;
     21 import java.util.List;
     22 import junit.framework.TestCase;
     23 import org.junit.Rule;
     24 import org.junit.rules.MethodRule;
     25 import org.junit.rules.TestRule;
     26 import org.junit.runner.Description;
     27 import org.junit.runners.model.FrameworkMethod;
     28 import org.junit.runners.model.MultipleFailureException;
     29 import org.junit.runners.model.Statement;
     30 import org.junit.runners.model.TestClass;
     31 
     32 import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_VALIDATOR;
     33 
     34 /**
     35  * A {@link TestCase} that supports the @Rule annotation from JUnit 4.
     36  *
     37  * <p>It supports both {@link TestRule} and {@link MethodRule} based rules when used with the
     38  * {@code @Rule} annotation on public fields and methods. The rules encapsulate the
     39  * {@link TestCase#runBare()} method and so are run before the {@link TestCase#setUp()} and after
     40  * the {@link TestCase#tearDown()} methods.
     41  *
     42  * <p>Classes that extend this must have a single no argument constructor.
     43  */
     44 public abstract class TestCaseWithRules extends TestCase {
     45 
     46     private final TestClass testClass;
     47 
     48     private final List<Throwable> validationErrors;
     49 
     50     public TestCaseWithRules() {
     51         testClass = new TestClass(getClass());
     52 
     53         validationErrors = new ArrayList<>();
     54         RULE_VALIDATOR.validate(testClass, validationErrors);
     55     }
     56 
     57     @Override
     58     public void runBare() throws Throwable {
     59         if (!validationErrors.isEmpty()) {
     60             throw new MultipleFailureException(validationErrors);
     61         }
     62 
     63         Statement statement = new Statement() {
     64             @Override
     65             public void evaluate() throws Throwable {
     66                 superRunBare();
     67             }
     68         };
     69 
     70         final String name = getName();
     71         FrameworkMethod frameworkMethod;
     72         try {
     73             Method method = getClass().getMethod(name, (Class[]) null);
     74             frameworkMethod = new FrameworkMethod(method);
     75         } catch (NoSuchMethodException e) {
     76             frameworkMethod = new FrameworkMethod(null) {
     77                 @Override
     78                 public String getName() {
     79                     return name;
     80                 }
     81 
     82                 @Override
     83                 public Annotation[] getAnnotations() {
     84                     return new Annotation[0];
     85                 }
     86 
     87                 @Override
     88                 public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
     89                     return null;
     90                 }
     91             };
     92         }
     93         Description description =
     94                 Description.createTestDescription(getClass(), frameworkMethod.getName(),
     95                         frameworkMethod.getAnnotations());
     96 
     97         List<Object> rules = testClass.getAnnotatedFieldValues(this, Rule.class, Object.class);
     98         for (Object rule : rules) {
     99             if (rule instanceof TestRule) {
    100                 statement = ((TestRule) rule).apply(statement, description);
    101             } else {
    102                 statement = ((MethodRule) rule).apply(statement, frameworkMethod, this);
    103             }
    104         }
    105 
    106         statement.evaluate();
    107     }
    108 
    109     private void superRunBare() throws Throwable {
    110         super.runBare();
    111     }
    112 }
    113