CachedSupplier implements Supplier<T> { @Override public T get() { return Try.of(() -> cache.get(Boolean.TRUE)).get(); } CachedSupplier(Try.CheckedSupplier<T> delegate, Time time);   CachedSupplier(Try.CheckedSupplier<T> delegate, Time time, Duration timeout); @Override T get();  }
@Test public void testCachesCalls() throws Throwable { var a = sut.get(); assertThat(a, is(INITIAL_VALUE)); verify(delegate, times(1)).get(); lenient().when(delegate.get()).thenReturn(NEW_VALUE); var b = sut.get(); assertThat(b, is(INITIAL_VALUE)); verifyNoMoreInteractions(delegate); }
@Test public void testReturnsOldValueIfDelegateFails() throws Throwable { var a = sut.get(); assertThat(a, is(INITIAL_VALUE)); verify(delegate, times(1)).get(); when(delegate.get()).thenThrow(new RuntimeException("Fail!")); now = now.plus(TIMEOUT).plusSeconds(1); var b = sut.get(); assertThat(b, is(INITIAL_VALUE)); exception.expect(ConditionTimeoutException.class); await().atMost(5, SECONDS).until(() -> sut.get() != INITIAL_VALUE); }
@Test public void testCacheRefreshes() throws Throwable { var a = sut.get(); assertThat(a, is(INITIAL_VALUE)); verify(delegate, times(1)).get(); when(delegate.get()).thenReturn(NEW_VALUE); now = now.plus(TIMEOUT).plusSeconds(1); await().until(() -> sut.get() == NEW_VALUE); }
@Test public void testCacheDoesNotRefreshBeforeTimeout() throws Throwable { int a = sut.get(); assertThat(a, is(INITIAL_VALUE)); verify(delegate, times(1)).get(); lenient().when(delegate.get()).thenReturn(NEW_VALUE); now = now.plus(TIMEOUT).minusSeconds(1); int b = sut.get(); assertThat(b, is(INITIAL_VALUE)); Thread.sleep(5000); verifyNoMoreInteractions(delegate); }
@Test public void shouldOnlyComputeOnceForConcurrentCalls() throws Throwable { var executor = Executors.newCachedThreadPool(); var queue = new LinkedBlockingQueue<Integer>(); when(delegate.get()).then(a -> queue.take()); var f1 = CompletableFuture.supplyAsync(sut, executor); var f2 = CompletableFuture.supplyAsync(sut, executor); verify(delegate, timeout(5000).times(1)).get(); queue.put(1); queue.put(2); assertThat(f1.join(), is(1)); assertThat(f2.join(), is(1)); Thread.sleep(5000); verifyNoMoreInteractions(delegate); }
@Test public void defaultTimeout() throws Throwable { sut = new CachedSupplier<>(delegate, time); var a = sut.get(); assertThat(a, is(INITIAL_VALUE)); verify(delegate, times(1)).get(); when(delegate.get()).thenReturn(NEW_VALUE); now = now.plus(DEFAULT_TIMEOUT).plusSeconds(1); await().until(() -> sut.get() == NEW_VALUE); }
@Test public void refreshesAsynchronously() throws Throwable { var initialValue = sut.get(); assertThat(initialValue, is(INITIAL_VALUE)); verify(delegate).get(); var reloadFuture = new CompletableFuture<Integer>(); when(delegate.get()).then(a -> reloadFuture.join()); now = now.plus(TIMEOUT).plusSeconds(1); var triggerValue = sut.get(); assertThat(triggerValue, is(INITIAL_VALUE)); await().until(() -> Try.of(() -> verify(delegate, times(2)).get()).isSuccess()); reloadFuture.complete(NEW_VALUE); await().until(() -> sut.get() == NEW_VALUE); }