Home | History | Annotate | Download | only in mockitoutil
      1 /*
      2  * Copyright (c) 2007 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 
      6 package org.mockitoutil;
      7 
      8 import org.junit.rules.TestRule;
      9 import org.junit.runner.Description;
     10 import org.junit.runners.model.Statement;
     11 
     12 import static java.lang.String.format;
     13 
     14 public class RetryRule implements TestRule {
     15     private final TestRule innerRule;
     16 
     17     public static RetryRule attempts(final int attempts) {
     18         return new RetryRule(new NumberedAttempts(attempts));
     19     }
     20 
     21     private RetryRule(TestRule innerRule) {
     22         this.innerRule = innerRule;
     23     }
     24 
     25     public Statement apply(final Statement base, final Description description) {
     26         return innerRule.apply(base, description);
     27     }
     28 
     29     private static class NumberedAttempts implements TestRule {
     30         private final int attempts;
     31 
     32         NumberedAttempts(int attempts) {
     33             assert attempts > 1;
     34             this.attempts = attempts;
     35         }
     36 
     37         @Override
     38         public Statement apply(final Statement base, final Description description) {
     39             return new Statement() {
     40                 @Override
     41                 public void evaluate() throws Throwable {
     42                     for (int remainingAttempts = attempts; remainingAttempts > 0 ; remainingAttempts--) {
     43                         try {
     44                             base.evaluate();
     45                         } catch (Throwable throwable) {
     46                             if (remainingAttempts < 0) {
     47                                 throw new AssertionError(format("Tried this test + %d times and failed", attempts))
     48                                         .initCause(throwable);
     49                             }
     50                         }
     51                     }
     52                 }
     53             };
     54         }
     55     }
     56 }
     57