### Question:
MultiRetryStrategy implements RetryStrategy<INPUT,OUTPUT> { @Override public OUTPUT apply( INPUT retriableInput, Function<INPUT,OUTPUT> retriable, Predicate<OUTPUT> wasRetrySuccessful ) { Log log = logProvider.getLog( MultiRetryStrategy.class ); OUTPUT result = retriable.apply( retriableInput ); int currentIteration = 0; while ( !wasRetrySuccessful.test( result ) && currentIteration++ < retries ) { log.debug( "Try attempt was unsuccessful for input: %s\n", retriableInput ); sleeper.accept( delayInMillis ); result = retriable.apply( retriableInput ); } return result; } MultiRetryStrategy( long delayInMillis, long retries, LogProvider logProvider, LongConsumer sleeper ); @Override OUTPUT apply( INPUT retriableInput, Function<INPUT,OUTPUT> retriable, Predicate<OUTPUT> wasRetrySuccessful );  }### Answer:
@Test public void successOnRetryCausesNoDelay() { CountingSleeper countingSleeper = new CountingSleeper(); int retries = 10; MultiRetryStrategy<Integer,Integer> subject = new MultiRetryStrategy<>( 0, retries, NullLogProvider.getInstance(), countingSleeper ); Integer result = subject.apply( 3, Function.identity(), ALWAYS_VALID ); assertEquals( 0, countingSleeper.invocationCount() ); assertEquals( "Function identity should be used to retrieve the expected value", 3, result.intValue() ); }
@Test public void numberOfIterationsDoesNotExceedMaximum() { CountingSleeper countingSleeper = new CountingSleeper(); int retries = 5; MultiRetryStrategy<Integer,Integer> subject = new MultiRetryStrategy<>( 0, retries, NullLogProvider.getInstance(), countingSleeper ); subject.apply( 3, Function.identity(), NEVER_VALID ); assertEquals( retries, countingSleeper.invocationCount() ); }
@Test public void successfulRetriesBreakTheRetryLoop() { CountingSleeper countingSleeper = new CountingSleeper(); int retries = 5; MultiRetryStrategy<Integer,Integer> subject = new MultiRetryStrategy<>( 0, retries, NullLogProvider.getInstance(), countingSleeper ); subject.apply( 3, Function.identity(), VALID_ON_SECOND_TIME ); assertEquals( 1, countingSleeper.invocationCount() ); }