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