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 17 package vogar.target.junit; 18 19 import java.util.ArrayList; 20 import java.util.List; 21 import org.junit.rules.TestRule; 22 import org.junit.runners.model.FrameworkMethod; 23 import org.junit.runners.model.InitializationError; 24 import org.junit.runners.model.Statement; 25 26 /** 27 * Defers the validation of test methods until just before they are run. 28 * 29 * <p>This does not throw an {@link InitializationError} during construction if a test method, i.e. 30 * one marked with {@link org.junit.Test @Test} annotation, is not valid. Instead it waits until the 31 * test is actually run until it does that. This is better than the standard JUnit behavior, where 32 * a single invalid test method would prevent all methods in the class from being run. 33 */ 34 public class ValidateTestMethodWhenRunBlockJUnit4ClassRunner 35 extends ApplyGlobalRulesBlockJUnit4ClassRunner { 36 ValidateTestMethodWhenRunBlockJUnit4ClassRunner(Class<?> klass, TestRule testRule)37 protected ValidateTestMethodWhenRunBlockJUnit4ClassRunner(Class<?> klass, TestRule testRule) 38 throws InitializationError { 39 super(klass, testRule); 40 } 41 42 @Override validateTestMethods(List<Throwable> errors)43 protected void validateTestMethods(List<Throwable> errors) { 44 // Overridden to avoid validation during initialization. 45 } 46 47 @Override methodInvoker(final FrameworkMethod frameworkMethod, Object test)48 protected Statement methodInvoker(final FrameworkMethod frameworkMethod, Object test) { 49 // Overridden to perform validation of the method. 50 Statement statement = super.methodInvoker(frameworkMethod, test); 51 52 // Wrap the Statement that will invoke the method with one that will validate that the 53 // method is of the correct form. 54 return new ValidateMethodStatement(frameworkMethod, statement); 55 } 56 57 /** 58 * A {@link Statement} that validates the underlying {@link FrameworkMethod} 59 */ 60 protected static class ValidateMethodStatement extends Statement { 61 private final FrameworkMethod frameworkMethod; 62 private final Statement methodInvoker; 63 ValidateMethodStatement(FrameworkMethod frameworkMethod, Statement methodInvoker)64 public ValidateMethodStatement(FrameworkMethod frameworkMethod, Statement methodInvoker) { 65 this.frameworkMethod = frameworkMethod; 66 this.methodInvoker = methodInvoker; 67 } 68 69 @Override evaluate()70 public void evaluate() throws Throwable { 71 validateFrameworkMethod(); 72 methodInvoker.evaluate(); 73 } 74 validateFrameworkMethod()75 private void validateFrameworkMethod() throws Throwable { 76 ArrayList<Throwable> errors = new ArrayList<>(); 77 frameworkMethod.validatePublicVoidNoArg(false, errors); 78 if (!errors.isEmpty()) { 79 throw errors.get(0); 80 } 81 } 82 } 83 } 84