### Question:
Resilient { public static <T> T tryRepeatedly(IoAction<T> action) throws IOException { return tryRepeatedly(10, action); }  static T tryRepeatedly(IoAction<T> action); static T tryRepeatedly(int maxTries, IoAction<T> action);  }### Answer:
@Test public void executes_once_if_there_is_no_exception() throws IOException { String result = Resilient.tryRepeatedly(10, () -> "result"); assertThat(result, is("result")); }
@Test public void retries_if_there_is_a_flaky_exception() throws IOException { AtomicInteger invocation = new AtomicInteger(0); String result = Resilient.tryRepeatedly(10, () -> { if (invocation.incrementAndGet() == 1) { throw new IOException("dummy exception"); } return "result"; }); assertThat(result, is("result")); }
@Test public void gives_up_and_rethrows_the_exception_if_fails_too_many_times() { int maxTries = 3; AtomicInteger invocations = new AtomicInteger(0); try { Resilient.tryRepeatedly(maxTries, () -> { invocations.incrementAndGet(); throw new IOException("dummy exception"); }); fail("should have thrown IOException"); } catch (IOException e) { assertThat("exception message", e.getMessage(), is("dummy exception")); assertThat("invocations", invocations.get(), is(maxTries)); } }