### Question:
MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier extends ForwardingObject implements
      Supplier<T> { @Override public T get() { try { return cache.get("FOO").orNull(); } catch (UncheckedExecutionException e) { throw propagate(e.getCause()); } catch (ExecutionException e) { throw propagate(e.getCause()); } } MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier(AtomicReference<AuthorizationException> authException,
         Supplier<T> delegate, long duration, TimeUnit unit, ValueLoadedCallback<T> valueLoadedCallback); static MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T> create(
         AtomicReference<AuthorizationException> authException, Supplier<T> delegate, long duration, TimeUnit unit); static MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T> create(
         AtomicReference<AuthorizationException> authException, Supplier<T> delegate, long duration, TimeUnit unit,
         ValueLoadedCallback<T> valueLoadedCallback); @Override T get(); @Override String toString();  }### Answer:
@Test public void testLoaderNormal() { AtomicReference<AuthorizationException> authException = newReference(); assertEquals(new SetAndThrowAuthorizationExceptionSupplierBackedLoader<String>(ofInstance("foo"), authException, new ValueLoadedCallback.NoOpCallback<String>()).load("KEY").get(), "foo"); assertEquals(authException.get(), null); }
@Test(expectedExceptions = AuthorizationException.class) public void testLoaderThrowsAuthorizationExceptionAndAlsoSetsExceptionType() { AtomicReference<AuthorizationException> authException = newReference(); try { new SetAndThrowAuthorizationExceptionSupplierBackedLoader<String>(new Supplier<String>() { public String get() { throw new AuthorizationException(); } }, authException, new ValueLoadedCallback.NoOpCallback<String>()).load("KEY"); } finally { assertEquals(authException.get().getClass(), AuthorizationException.class); } }
@Test(expectedExceptions = AuthorizationException.class) public void testLoaderThrowsAuthorizationExceptionAndAlsoSetsExceptionTypeWhenNested() { AtomicReference<AuthorizationException> authException = newReference(); try { new SetAndThrowAuthorizationExceptionSupplierBackedLoader<String>(new Supplier<String>() { public String get() { throw new RuntimeException(new ExecutionException(new AuthorizationException())); } }, authException, new ValueLoadedCallback.NoOpCallback<String>()).load("KEY"); } finally { assertEquals(authException.get().getClass(), AuthorizationException.class); } }
@Test(expectedExceptions = AuthorizationException.class) public void testLoaderThrowsAuthorizationExceptionAndAlsoSetsExceptionTypeWhenInUncheckedExecutionException() { AtomicReference<AuthorizationException> authException = newReference(); try { new SetAndThrowAuthorizationExceptionSupplierBackedLoader<String>(new Supplier<String>() { public String get() { throw new UncheckedExecutionException(new AuthorizationException()); } }, authException, new ValueLoadedCallback.NoOpCallback<String>()).load("KEY"); } finally { assertEquals(authException.get().getClass(), AuthorizationException.class); } }
@Test(expectedExceptions = RuntimeException.class) public void testLoaderThrowsOriginalExceptionAndAlsoSetsExceptionTypeWhenNestedAndNotAuthorizationException() { AtomicReference<AuthorizationException> authException = newReference(); try { new SetAndThrowAuthorizationExceptionSupplierBackedLoader<String>(new Supplier<String>() { public String get() { throw new RuntimeException(new IllegalArgumentException("foo")); } }, authException, new ValueLoadedCallback.NoOpCallback<String>()).load("KEY"); } finally { assertEquals(authException.get().getClass(), RuntimeException.class); } }