### Question:
Saver implements InvocationHandler { @SuppressWarnings("unchecked") public I toProxy() { return (I) Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), new Class<?>[]{ interfaceType }, this ); } Saver(Class<I> interfaceType, D delegate); static Saver<I, D> aSaver(Class<I> interfaceType, D delegate); @SuppressWarnings("unchecked") I toProxy(); @Override Object invoke(Object proxy, Method method, Object[] args);  }### Answer:
@Test public void redirect_only_the_call_when_method_has_no_annotations() { ProductProvider provider = saver.toProxy(); provider.setSomething(5); assertEquals(5, delegate.something); }
@Test public void returns_cached_object_when_delegate_method_is_annotated_and_cache_contains_a_value_for_the_same_key() throws ExecutionException { final List<Product> expectedProducts = Arrays.asList(new Product(1L, "Laptop", Category.hardware)); context.checking(new Expectations() {{ oneOf(cache).get(with(any(CallKey.class))); will(returnValue(expectedProducts)); }}); ProductProvider provider = saver.toProxy(); List<Product> products = provider.loadAllByCategory(Category.hardware); assertEquals(expectedProducts, products); }
@Test public void call_underline_object_when_cache_does_not_contain_data_anymore() throws ExecutionException { ProductProvider provider = saver.toProxy(); context.checking(new Expectations() {{ oneOf(cache).get(with(any(CallKey.class))); will(returnValue(null)); oneOf(cache).put(with(any(CallKey.class)), with(any(List.class))); }}); List<Product> products = provider.loadAllByCategory(Category.hardware); assertEquals(ProductProviderSlow.PRODUCTS, products); }