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