class CachingHttpClient {

    public synchronized T get(URL url) throws IOException {
        if (url == null) {
            throw new IllegalArgumentException("URL must not be null");
        }

        Optional<byte[]> content = Optional.empty();
        try {
            content = cache.get(url, () -> Optional.of(getContent(url)));
        } catch (ExecutionException e) {
            cache.put(url, Optional.empty());
            throw new IOException("Unable to get " + url.toString(), e.getCause());
        }
        return content.isPresent() ? callback.transform(content.get()) : null;
    }

}

class CachingHttpClientTest {

    private static final String PATH_TO_RESOURCE;
    private static final String PATH_TO_MISSING_RESOURCE;
    private static final int TEST_PORT;
    private static final String TEST_HOST;
    private static final int TEST_TIMEOUT;
    private static final String SERVER_RESPONSE;
    private static Server server;
    private ContentReceviedCallback<String> testCallback;
    private CachingHttpClient<String> testClient;

    @Test
    public void testMultipleSuccessfulRequests() throws Exception {

        URL reachableURL = getUniqueURL(PATH_TO_RESOURCE);

        assertNotNull(testClient.get(reachableURL));
        assertNotNull(testClient.get(reachableURL));
        assertNotNull(testClient.get(reachableURL));

        verify(server.getHandler(), times(1)).handle(any(), any(), any(), any());
    }

}