CachedTransformingSupplier implements Supplier<U> { @Override public synchronized U get() { T currentInput = inputSupplier.get(); if (Objects.equals(cachedInput, currentInput)) { return cachedOutput; } cachedInput = currentInput; cachedOutput = outputFunction.apply(cachedInput); return cachedOutput; } CachedTransformingSupplier(Supplier<T> inputSupplier, Function<T, U> outputFunction); @Override synchronized U get();  }
@Test public void getsFreshValuesFromSupplier() { when(STRING_SUPPLIER.get()) .thenReturn("42") .thenReturn("4242"); assertThat(TRANSFORMING_SUPPLIER.get()).isEqualTo(42); assertThat(TRANSFORMING_SUPPLIER.get()).isEqualTo(4242); }
@Test public void onlyCallsTransformOnceIfUnderlyingValueNotChanged() { when(STRING_SUPPLIER.get()).thenReturn("42"); IntStream.range(0, 10).forEach( $ -> assertThat(TRANSFORMING_SUPPLIER.get()).isEqualTo(42)); verify(STRING_SUPPLIER, times(10)).get(); verify(LONG_FUNCTION, times(1)).apply(anyString()); }
@Test public void throwsIfSupplierThrows() { RuntimeException ex = new RuntimeException(); when(STRING_SUPPLIER.get()).thenThrow(ex); assertThatThrownBy(TRANSFORMING_SUPPLIER::get).isEqualTo(ex); }
@Test public void throwsIfMappingFunctionThrows() { when(STRING_SUPPLIER.get()).thenReturn("42!)*()"); assertThatThrownBy(TRANSFORMING_SUPPLIER::get).isInstanceOf(NumberFormatException.class); }