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