public async Task Caches_the_result()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler));

            // execute twice
            await client.GetAsync("http://unittest");
            await client.GetAsync("http://unittest");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(1);
        }
        public async Task Returns_response_header()
        {
            // setup
            var testMessageHandler = new TestMessageHandler(System.Net.HttpStatusCode.OK, "test content", "text/plain", System.Text.Encoding.UTF8);
            var client             = new HttpClient(new InMemoryCacheHandler(testMessageHandler));

            // execute
            HttpResponseMessage response = await client.GetAsync("http://unittest");

            // validate
            response.Content.Headers.ContentType.MediaType.Should().Be("text/plain");
            response.Content.Headers.ContentType.CharSet.Should().Be("utf-8");
        }
        public async Task Caches_per_url()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute for different URLs
            await client.GetAsync("http://unittest1");
            await client.GetAsync("http://unittest2");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Is_case_sensitive()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute for different URLs, only different by casing
            await client.GetAsync("http://unittest/foo.html");
            await client.GetAsync("http://unittest/FOO.html");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Caches_head_and_get_request_without_conflict()
        {
            var testMessageHandler = new TestMessageHandler();
            var cache  = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute twice for different methods
            await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, "http://unittest"));

            await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "http://unittest"));

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Caches_the_result()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var client             = new HttpClient(new InMemoryCacheHandler(testMessageHandler));

            // execute twice
            await client.GetAsync("http://unittest");

            await client.GetAsync("http://unittest");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(1);
        }
        public async Task Gets_the_data_again_after_entry_is_gone_from_cache()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute twice
            await client.GetAsync("http://unittest");
            cache.Remove(new Uri("http://unittest"));
            await client.GetAsync("http://unittest");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Caches_per_url()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache  = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute for different URLs
            await client.GetAsync("http://unittest1");

            await client.GetAsync("http://unittest2");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Is_case_sensitive()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache  = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute for different URLs, only different by casing
            await client.GetAsync("http://unittest/foo.html");

            await client.GetAsync("http://unittest/FOO.html");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Always_calls_the_http_handler()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache  = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheFallbackHandler(testMessageHandler, TimeSpan.FromDays(1), TimeSpan.FromDays(1), null, cache));

            // execute twice
            await client.GetAsync(url);

            cache.Get(InMemoryCacheFallbackHandler.CacheFallbackKeyPrefix + HttpMethod.Get + url).Should().NotBeNull(); // ensure it's cached before the 2nd call
            await client.GetAsync(url);

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Gets_the_data_again_after_entry_is_gone_from_cache()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache  = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute twice
            await client.GetAsync("http://unittest");

            cache.Remove(HttpMethod.Get + new Uri("http://unittest").ToString());
            await client.GetAsync("http://unittest");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Tries_to_access_cache_on_failure_but_returns_error_if_not_in_cache()
        {
            // setup
            var    testMessageHandler = new TestMessageHandler(HttpStatusCode.InternalServerError);
            var    cache     = new Mock <IMemoryCache>(MockBehavior.Strict);
            var    cacheTime = TimeSpan.FromSeconds(123);
            object expectedValue;

            cache.Setup(c => c.TryGetValue(url, out expectedValue)).Returns(false);
            var client = new HttpClient(new InMemoryCacheFallbackHandler(testMessageHandler, TimeSpan.FromDays(1), cacheTime, null, cache.Object));

            // execute
            var result = await client.GetAsync(url);

            // validate
            result.StatusCode.Should().Be(HttpStatusCode.InternalServerError);
        }
        public async Task Invalidates_cache_correctly()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var handler            = new InMemoryCacheHandler(testMessageHandler);
            var client             = new HttpClient(handler);

            // execute twice, with cache invalidation in between
            var uri = new Uri("http://unittest");
            await client.GetAsync(uri);

            handler.InvalidateCache(uri);
            await client.GetAsync(uri);

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Only_caches_get_results()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute twice for different methods
            await client.PostAsync("http://unittest", new StringContent(string.Empty));
            await client.PostAsync("http://unittest", new StringContent(string.Empty));
            await client.PutAsync("http://unittest", new StringContent(string.Empty));
            await client.PutAsync("http://unittest", new StringContent(string.Empty));
            await client.DeleteAsync("http://unittest");
            await client.DeleteAsync("http://unittest");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(6);
        }
        public async Task Disable_cache_per_statusCode()
        {
            // setup
            var cacheExpirationPerStatusCode = new Dictionary <HttpStatusCode, TimeSpan>();

            cacheExpirationPerStatusCode.Add((HttpStatusCode)200, TimeSpan.FromSeconds(0));

            var testMessageHandler = new TestMessageHandler();
            var client             = new HttpClient(new InMemoryCacheHandler(testMessageHandler, cacheExpirationPerStatusCode));

            // execute twice
            await client.GetAsync("http://unittest");

            await client.GetAsync("http://unittest");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(2);
        }
        public async Task Never_updates_the_cache_on_failure()
        {
            // setup
            var    testMessageHandler = new TestMessageHandler(HttpStatusCode.InternalServerError);
            var    cache     = new Mock <IMemoryCache>(MockBehavior.Strict);
            var    cacheTime = TimeSpan.FromSeconds(123);
            object expectedValue;

            cache.Setup(c => c.CreateEntry(It.IsAny <string>()));
            cache.Setup(c => c.TryGetValue(url, out expectedValue)).Returns(false);
            var client = new HttpClient(new InMemoryCacheFallbackHandler(testMessageHandler, TimeSpan.FromDays(1), cacheTime, null, cache.Object));

            // execute
            await client.GetAsync(url);

            // validate
            cache.Verify(c => c.CreateEntry(It.IsAny <string>()), Times.Never);
        }
        public async Task Always_updates_the_cache_on_success()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache     = new Mock <IMemoryCache>(MockBehavior.Strict);
            var cacheTime = TimeSpan.FromSeconds(123);

            cache.Setup(c => c.CreateEntry(InMemoryCacheFallbackHandler.CacheFallbackKeyPrefix + HttpMethod.Get + url));
            var client = new HttpClient(new InMemoryCacheFallbackHandler(testMessageHandler, TimeSpan.FromDays(1), cacheTime, null, cache.Object));

            // execute twice, validate cache is called each time
            await client.GetAsync(url);

            cache.Verify(c => c.CreateEntry(InMemoryCacheFallbackHandler.CacheFallbackKeyPrefix + HttpMethod.Get + url), Times.Once);
            await client.GetAsync(url);

            cache.Verify(c => c.CreateEntry(InMemoryCacheFallbackHandler.CacheFallbackKeyPrefix + HttpMethod.Get + url), Times.Exactly(2));
        }
        public async Task Updates_the_cache_for_head_and_get_independently()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache     = new Mock <IMemoryCache>(MockBehavior.Strict);
            var cacheTime = TimeSpan.FromSeconds(123);

            cache.Setup(c => c.CreateEntry(InMemoryCacheFallbackHandler.CacheFallbackKeyPrefix + HttpMethod.Get + url));
            cache.Setup(c => c.CreateEntry(InMemoryCacheFallbackHandler.CacheFallbackKeyPrefix + HttpMethod.Head + url));
            var client = new HttpClient(new InMemoryCacheFallbackHandler(testMessageHandler, TimeSpan.FromDays(1), cacheTime, null, cache.Object));

            // execute twice, validate cache is called each time
            await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, url));

            await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, url));

            cache.Verify(c => c.CreateEntry(InMemoryCacheFallbackHandler.CacheFallbackKeyPrefix + HttpMethod.Head + url), Times.Once);
            cache.Verify(c => c.CreateEntry(InMemoryCacheFallbackHandler.CacheFallbackKeyPrefix + HttpMethod.Get + url), Times.Once);
        }
        public async Task Data_from_call_matches_data_from_cache()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache  = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute twice for different methods
            var originalResult = await client.GetAsync("http://unittest");

            var cachedResult = await client.GetAsync("http://unittest");

            var originalResultString = await originalResult.Content.ReadAsStringAsync();

            var cachedResultString = await cachedResult.Content.ReadAsStringAsync();

            // validate
            originalResultString.ShouldBeEquivalentTo(cachedResultString);
            originalResultString.ShouldBeEquivalentTo(TestMessageHandler.DefaultContent);
        }
        public async Task Only_caches_get_and_head_results()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache  = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute twice for different methods
            await client.PostAsync("http://unittest", new StringContent(string.Empty));

            await client.PostAsync("http://unittest", new StringContent(string.Empty));

            await client.PutAsync("http://unittest", new StringContent(string.Empty));

            await client.PutAsync("http://unittest", new StringContent(string.Empty));

            await client.DeleteAsync("http://unittest");

            await client.DeleteAsync("http://unittest");

            // validate
            testMessageHandler.NumberOfCalls.Should().Be(6);
        }
        public async Task Data_from_call_matches_data_from_cache()
        {
            // setup
            var testMessageHandler = new TestMessageHandler();
            var cache = new MemoryCache(new MemoryCacheOptions());
            var client = new HttpClient(new InMemoryCacheHandler(testMessageHandler, null, null, cache));

            // execute twice for different methods
            var originalResult = await client.GetAsync("http://unittest");
            var cachedResult = await client.GetAsync("http://unittest");
            var originalResultString = await originalResult.Content.ReadAsStringAsync();
            var cachedResultString = await cachedResult.Content.ReadAsStringAsync();

            // validate
            originalResultString.ShouldBeEquivalentTo(cachedResultString);
            originalResultString.ShouldBeEquivalentTo(TestMessageHandler.DefaultContent);
        }