001 package org.junit.runners; 002 003 import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_METHOD_VALIDATOR; 004 import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_VALIDATOR; 005 006 import java.util.List; 007 import java.util.concurrent.ConcurrentHashMap; 008 009 import org.junit.After; 010 import org.junit.Before; 011 import org.junit.Ignore; 012 import org.junit.Rule; 013 import org.junit.Test; 014 import org.junit.Test.None; 015 import org.junit.internal.runners.model.ReflectiveCallable; 016 import org.junit.internal.runners.statements.ExpectException; 017 import org.junit.internal.runners.statements.Fail; 018 import org.junit.internal.runners.statements.FailOnTimeout; 019 import org.junit.internal.runners.statements.InvokeMethod; 020 import org.junit.internal.runners.statements.RunAfters; 021 import org.junit.internal.runners.statements.RunBefores; 022 import org.junit.rules.RunRules; 023 import org.junit.rules.TestRule; 024 import org.junit.runner.Description; 025 import org.junit.runner.notification.RunNotifier; 026 import org.junit.runners.model.FrameworkMethod; 027 import org.junit.runners.model.InitializationError; 028 import org.junit.runners.model.MultipleFailureException; 029 import org.junit.runners.model.Statement; 030 031 /** 032 * Implements the JUnit 4 standard test case class model, as defined by the 033 * annotations in the org.junit package. Many users will never notice this 034 * class: it is now the default test class runner, but it should have exactly 035 * the same behavior as the old test class runner ({@code JUnit4ClassRunner}). 036 * <p> 037 * BlockJUnit4ClassRunner has advantages for writers of custom JUnit runners 038 * that are slight changes to the default behavior, however: 039 * 040 * <ul> 041 * <li>It has a much simpler implementation based on {@link Statement}s, 042 * allowing new operations to be inserted into the appropriate point in the 043 * execution flow. 044 * 045 * <li>It is published, and extension and reuse are encouraged, whereas {@code 046 * JUnit4ClassRunner} was in an internal package, and is now deprecated. 047 * </ul> 048 * <p> 049 * In turn, in 2009 we introduced {@link Rule}s. In many cases where extending 050 * BlockJUnit4ClassRunner was necessary to add new behavior, {@link Rule}s can 051 * be used, which makes the extension more reusable and composable. 052 * 053 * @since 4.5 054 */ 055 public class BlockJUnit4ClassRunner extends ParentRunner<FrameworkMethod> { 056 private final ConcurrentHashMap<FrameworkMethod, Description> methodDescriptions = new ConcurrentHashMap<FrameworkMethod, Description>(); 057 /** 058 * Creates a BlockJUnit4ClassRunner to run {@code klass} 059 * 060 * @throws InitializationError if the test class is malformed. 061 */ 062 public BlockJUnit4ClassRunner(Class<?> klass) throws InitializationError { 063 super(klass); 064 } 065 066 // 067 // Implementation of ParentRunner 068 // 069 070 @Override 071 protected void runChild(final FrameworkMethod method, RunNotifier notifier) { 072 Description description = describeChild(method); 073 if (isIgnored(method)) { 074 notifier.fireTestIgnored(description); 075 } else { 076 runLeaf(methodBlock(method), description, notifier); 077 } 078 } 079 080 /** 081 * Evaluates whether {@link FrameworkMethod}s are ignored based on the 082 * {@link Ignore} annotation. 083 */ 084 @Override 085 protected boolean isIgnored(FrameworkMethod child) { 086 return child.getAnnotation(Ignore.class) != null; 087 } 088 089 @Override 090 protected Description describeChild(FrameworkMethod method) { 091 Description description = methodDescriptions.get(method); 092 093 if (description == null) { 094 description = Description.createTestDescription(getTestClass().getJavaClass(), 095 testName(method), method.getAnnotations()); 096 methodDescriptions.putIfAbsent(method, description); 097 } 098 099 return description; 100 } 101 102 @Override 103 protected List<FrameworkMethod> getChildren() { 104 return computeTestMethods(); 105 } 106 107 // 108 // Override in subclasses 109 // 110 111 /** 112 * Returns the methods that run tests. Default implementation returns all 113 * methods annotated with {@code @Test} on this class and superclasses that 114 * are not overridden. 115 */ 116 protected List<FrameworkMethod> computeTestMethods() { 117 return getTestClass().getAnnotatedMethods(Test.class); 118 } 119 120 @Override 121 protected void collectInitializationErrors(List<Throwable> errors) { 122 super.collectInitializationErrors(errors); 123 124 validateNoNonStaticInnerClass(errors); 125 validateConstructor(errors); 126 validateInstanceMethods(errors); 127 validateFields(errors); 128 validateMethods(errors); 129 } 130 131 protected void validateNoNonStaticInnerClass(List<Throwable> errors) { 132 if (getTestClass().isANonStaticInnerClass()) { 133 String gripe = "The inner class " + getTestClass().getName() 134 + " is not static."; 135 errors.add(new Exception(gripe)); 136 } 137 } 138 139 /** 140 * Adds to {@code errors} if the test class has more than one constructor, 141 * or if the constructor takes parameters. Override if a subclass requires 142 * different validation rules. 143 */ 144 protected void validateConstructor(List<Throwable> errors) { 145 validateOnlyOneConstructor(errors); 146 validateZeroArgConstructor(errors); 147 } 148 149 /** 150 * Adds to {@code errors} if the test class has more than one constructor 151 * (do not override) 152 */ 153 protected void validateOnlyOneConstructor(List<Throwable> errors) { 154 if (!hasOneConstructor()) { 155 String gripe = "Test class should have exactly one public constructor"; 156 errors.add(new Exception(gripe)); 157 } 158 } 159 160 /** 161 * Adds to {@code errors} if the test class's single constructor takes 162 * parameters (do not override) 163 */ 164 protected void validateZeroArgConstructor(List<Throwable> errors) { 165 if (!getTestClass().isANonStaticInnerClass() 166 && hasOneConstructor() 167 && (getTestClass().getOnlyConstructor().getParameterTypes().length != 0)) { 168 String gripe = "Test class should have exactly one public zero-argument constructor"; 169 errors.add(new Exception(gripe)); 170 } 171 } 172 173 private boolean hasOneConstructor() { 174 return getTestClass().getJavaClass().getConstructors().length == 1; 175 } 176 177 /** 178 * Adds to {@code errors} for each method annotated with {@code @Test}, 179 * {@code @Before}, or {@code @After} that is not a public, void instance 180 * method with no arguments. 181 */ 182 @Deprecated 183 protected void validateInstanceMethods(List<Throwable> errors) { 184 validatePublicVoidNoArgMethods(After.class, false, errors); 185 validatePublicVoidNoArgMethods(Before.class, false, errors); 186 validateTestMethods(errors); 187 188 if (computeTestMethods().size() == 0) { 189 errors.add(new Exception("No runnable methods")); 190 } 191 } 192 193 protected void validateFields(List<Throwable> errors) { 194 RULE_VALIDATOR.validate(getTestClass(), errors); 195 } 196 197 private void validateMethods(List<Throwable> errors) { 198 RULE_METHOD_VALIDATOR.validate(getTestClass(), errors); 199 } 200 201 /** 202 * Adds to {@code errors} for each method annotated with {@code @Test}that 203 * is not a public, void instance method with no arguments. 204 */ 205 protected void validateTestMethods(List<Throwable> errors) { 206 validatePublicVoidNoArgMethods(Test.class, false, errors); 207 } 208 209 /** 210 * Returns a new fixture for running a test. Default implementation executes 211 * the test class's no-argument constructor (validation should have ensured 212 * one exists). 213 */ 214 protected Object createTest() throws Exception { 215 return getTestClass().getOnlyConstructor().newInstance(); 216 } 217 218 /** 219 * Returns the name that describes {@code method} for {@link Description}s. 220 * Default implementation is the method's name 221 */ 222 protected String testName(FrameworkMethod method) { 223 return method.getName(); 224 } 225 226 /** 227 * Returns a Statement that, when executed, either returns normally if 228 * {@code method} passes, or throws an exception if {@code method} fails. 229 * 230 * Here is an outline of the default implementation: 231 * 232 * <ul> 233 * <li>Invoke {@code method} on the result of {@code createTest()}, and 234 * throw any exceptions thrown by either operation. 235 * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code 236 * expecting} attribute, return normally only if the previous step threw an 237 * exception of the correct type, and throw an exception otherwise. 238 * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code 239 * timeout} attribute, throw an exception if the previous step takes more 240 * than the specified number of milliseconds. 241 * <li>ALWAYS run all non-overridden {@code @Before} methods on this class 242 * and superclasses before any of the previous steps; if any throws an 243 * Exception, stop execution and pass the exception on. 244 * <li>ALWAYS run all non-overridden {@code @After} methods on this class 245 * and superclasses after any of the previous steps; all After methods are 246 * always executed: exceptions thrown by previous steps are combined, if 247 * necessary, with exceptions from After methods into a 248 * {@link MultipleFailureException}. 249 * <li>ALWAYS allow {@code @Rule} fields to modify the execution of the 250 * above steps. A {@code Rule} may prevent all execution of the above steps, 251 * or add additional behavior before and after, or modify thrown exceptions. 252 * For more information, see {@link TestRule} 253 * </ul> 254 * 255 * This can be overridden in subclasses, either by overriding this method, 256 * or the implementations creating each sub-statement. 257 */ 258 protected Statement methodBlock(FrameworkMethod method) { 259 Object test; 260 try { 261 test = new ReflectiveCallable() { 262 @Override 263 protected Object runReflectiveCall() throws Throwable { 264 return createTest(); 265 } 266 }.run(); 267 } catch (Throwable e) { 268 return new Fail(e); 269 } 270 271 Statement statement = methodInvoker(method, test); 272 statement = possiblyExpectingExceptions(method, test, statement); 273 statement = withPotentialTimeout(method, test, statement); 274 statement = withBefores(method, test, statement); 275 statement = withAfters(method, test, statement); 276 statement = withRules(method, test, statement); 277 return statement; 278 } 279 280 // 281 // Statement builders 282 // 283 284 /** 285 * Returns a {@link Statement} that invokes {@code method} on {@code test} 286 */ 287 protected Statement methodInvoker(FrameworkMethod method, Object test) { 288 return new InvokeMethod(method, test); 289 } 290 291 /** 292 * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation 293 * has the {@code expecting} attribute, return normally only if {@code next} 294 * throws an exception of the correct type, and throw an exception 295 * otherwise. 296 */ 297 protected Statement possiblyExpectingExceptions(FrameworkMethod method, 298 Object test, Statement next) { 299 Test annotation = method.getAnnotation(Test.class); 300 return expectsException(annotation) ? new ExpectException(next, 301 getExpectedException(annotation)) : next; 302 } 303 304 /** 305 * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation 306 * has the {@code timeout} attribute, throw an exception if {@code next} 307 * takes more than the specified number of milliseconds. 308 */ 309 @Deprecated 310 protected Statement withPotentialTimeout(FrameworkMethod method, 311 Object test, Statement next) { 312 long timeout = getTimeout(method.getAnnotation(Test.class)); 313 return timeout > 0 ? new FailOnTimeout(next, timeout) : next; 314 } 315 316 /** 317 * Returns a {@link Statement}: run all non-overridden {@code @Before} 318 * methods on this class and superclasses before running {@code next}; if 319 * any throws an Exception, stop execution and pass the exception on. 320 */ 321 protected Statement withBefores(FrameworkMethod method, Object target, 322 Statement statement) { 323 List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods( 324 Before.class); 325 return befores.isEmpty() ? statement : new RunBefores(statement, 326 befores, target); 327 } 328 329 /** 330 * Returns a {@link Statement}: run all non-overridden {@code @After} 331 * methods on this class and superclasses before running {@code next}; all 332 * After methods are always executed: exceptions thrown by previous steps 333 * are combined, if necessary, with exceptions from After methods into a 334 * {@link MultipleFailureException}. 335 */ 336 protected Statement withAfters(FrameworkMethod method, Object target, 337 Statement statement) { 338 List<FrameworkMethod> afters = getTestClass().getAnnotatedMethods( 339 After.class); 340 return afters.isEmpty() ? statement : new RunAfters(statement, afters, 341 target); 342 } 343 344 private Statement withRules(FrameworkMethod method, Object target, 345 Statement statement) { 346 List<TestRule> testRules = getTestRules(target); 347 Statement result = statement; 348 result = withMethodRules(method, testRules, target, result); 349 result = withTestRules(method, testRules, result); 350 351 return result; 352 } 353 354 private Statement withMethodRules(FrameworkMethod method, List<TestRule> testRules, 355 Object target, Statement result) { 356 for (org.junit.rules.MethodRule each : getMethodRules(target)) { 357 if (!testRules.contains(each)) { 358 result = each.apply(result, method, target); 359 } 360 } 361 return result; 362 } 363 364 private List<org.junit.rules.MethodRule> getMethodRules(Object target) { 365 return rules(target); 366 } 367 368 /** 369 * @param target the test case instance 370 * @return a list of MethodRules that should be applied when executing this 371 * test 372 */ 373 protected List<org.junit.rules.MethodRule> rules(Object target) { 374 return getTestClass().getAnnotatedFieldValues(target, Rule.class, 375 org.junit.rules.MethodRule.class); 376 } 377 378 /** 379 * Returns a {@link Statement}: apply all non-static fields 380 * annotated with {@link Rule}. 381 * 382 * @param statement The base statement 383 * @return a RunRules statement if any class-level {@link Rule}s are 384 * found, or the base statement 385 */ 386 private Statement withTestRules(FrameworkMethod method, List<TestRule> testRules, 387 Statement statement) { 388 return testRules.isEmpty() ? statement : 389 new RunRules(statement, testRules, describeChild(method)); 390 } 391 392 /** 393 * @param target the test case instance 394 * @return a list of TestRules that should be applied when executing this 395 * test 396 */ 397 protected List<TestRule> getTestRules(Object target) { 398 List<TestRule> result = getTestClass().getAnnotatedMethodValues(target, 399 Rule.class, TestRule.class); 400 401 result.addAll(getTestClass().getAnnotatedFieldValues(target, 402 Rule.class, TestRule.class)); 403 404 return result; 405 } 406 407 private Class<? extends Throwable> getExpectedException(Test annotation) { 408 if (annotation == null || annotation.expected() == None.class) { 409 return null; 410 } else { 411 return annotation.expected(); 412 } 413 } 414 415 private boolean expectsException(Test annotation) { 416 return getExpectedException(annotation) != null; 417 } 418 419 private long getTimeout(Test annotation) { 420 if (annotation == null) { 421 return 0; 422 } 423 return annotation.timeout(); 424 } 425 }