public async Task Tries_to_access_cache_on_failure_but_returns_error_if_not_in_cache(HttpMethod method) { // setup var testMessageHandler = new TestMessageHandler(HttpStatusCode.InternalServerError); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); var cacheTime = TimeSpan.FromSeconds(123); cache.Setup(c => c.GetAsync(method + url)).ReturnsAsync(default(byte[])); var client = new HttpClient(new RedisCacheFallbackHandler(testMessageHandler, TimeSpan.FromDays(1), cacheTime, cache.Object)); // execute var result = await client.SendAsync(new HttpRequestMessage(method, url)); // validate result.StatusCode.Should().Be(HttpStatusCode.InternalServerError); }
public async Task Only_caches_get_results() { // setup var testMessageHandler = new TestMessageHandler(); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary<HttpStatusCode, TimeSpan>(), (IDistributedCache) null)); // 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 Caches_per_url() { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock<IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync(It.IsAny<string>())).ReturnsAsync(null); cache.Setup(c => c.SetAsync(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<DistributedCacheEntryOptions>())).Returns(Task.FromResult(true)); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary<HttpStatusCode, TimeSpan>(), cache.Object)); // execute for different URLs await client.GetAsync("http://unittest1"); await client.GetAsync("http://unittest2"); // validate testMessageHandler.NumberOfCalls.Should().Be(2); cache.Verify(c => c.SetAsync(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<DistributedCacheEntryOptions>()), Times.Exactly(2)); }
public async Task Gets_the_data_again_after_entry_is_gone_from_cache() { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock<IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync("http://unittest/")).ReturnsAsync(null); cache.Setup(c => c.SetAsync("http://unittest/", It.IsAny<byte[]>(), It.IsAny<DistributedCacheEntryOptions>())).Returns(Task.FromResult(true)); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary<HttpStatusCode, TimeSpan>(), cache.Object)); // execute twice await client.GetAsync("http://unittest"); await client.GetAsync("http://unittest"); // validate testMessageHandler.NumberOfCalls.Should().Be(2); cache.Verify(c => c.GetAsync("http://unittest/"), Times.Exactly(2)); }
public async Task Never_updates_the_cache_on_failure(HttpMethod method) { // setup var testMessageHandler = new TestMessageHandler(HttpStatusCode.InternalServerError); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); var cacheTime = TimeSpan.FromSeconds(123); cache.Setup(c => c.SetAsync(It.IsAny <string>(), It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>())).Returns(Task.FromResult(true)); cache.Setup(c => c.GetAsync(method + url)).ReturnsAsync(default(byte[])); var client = new HttpClient(new RedisCacheFallbackHandler(testMessageHandler, TimeSpan.FromDays(1), cacheTime, cache.Object)); // execute await client.SendAsync(new HttpRequestMessage(method, url)); // validate cache.Verify(c => c.SetAsync(It.IsAny <string>(), It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>()), Times.Never); }
public async Task Always_calls_the_http_handler(HttpMethod method) { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.SetAsync(RedisCacheFallbackHandler.CacheFallbackKeyPrefix + method + url, It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>())).Returns(Task.FromResult(true)); var client = new HttpClient(new RedisCacheFallbackHandler(testMessageHandler, TimeSpan.FromDays(1), TimeSpan.FromDays(1), cache.Object)); // execute twice await client.SendAsync(new HttpRequestMessage(method, url)); cache.Verify(c => c.SetAsync(RedisCacheFallbackHandler.CacheFallbackKeyPrefix + method + url, It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>()), Times.Once); // ensure it's cached before the 2nd call await client.SendAsync(new HttpRequestMessage(method, url)); // validate testMessageHandler.NumberOfCalls.Should().Be(2); }
public void Ignores_set_cache_exceptions() { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock<IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync("http://unittest/")).ReturnsAsync(null); cache.Setup(c => c.SetAsync("http://unittest/", It.IsAny<byte[]>(), It.IsAny<DistributedCacheEntryOptions>())).Throws<Exception>(); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary<HttpStatusCode, TimeSpan>(), cache.Object)); // execute twice Func<Task<HttpResponseMessage>> func = async () => await client.GetAsync("http://unittest"); func.ShouldNotThrow(); // validate testMessageHandler.NumberOfCalls.Should().Be(1); cache.Verify(c => c.GetAsync("http://unittest/"), Times.Once); cache.Verify(c => c.SetAsync("http://unittest/", It.IsAny<byte[]>(), It.IsAny<DistributedCacheEntryOptions>()), Times.Once); }
public async Task Always_updates_the_cache_on_success(HttpMethod method) { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); var cacheTime = TimeSpan.FromSeconds(123); cache.Setup(c => c.SetAsync(method + url, It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>())).Returns(Task.FromResult(true)); var client = new HttpClient(new RedisCacheFallbackHandler(testMessageHandler, TimeSpan.FromDays(1), cacheTime, cache.Object)); // execute twice, validate cache is called each time await client.SendAsync(new HttpRequestMessage(method, url)); cache.Verify(c => c.SetAsync(RedisCacheFallbackHandler.CacheFallbackKeyPrefix + method + url, It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>()), Times.Once); await client.SendAsync(new HttpRequestMessage(method, url)); cache.Verify(c => c.SetAsync(RedisCacheFallbackHandler.CacheFallbackKeyPrefix + method + url, It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>()), Times.Exactly(2)); }
public async Task Caches_per_url_and_method(HttpMethod method) { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync(It.IsAny <string>(), It.IsAny <CancellationToken>())).ReturnsAsync(default(byte[])); cache.Setup(c => c.SetAsync(It.IsAny <string>(), It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(true)); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary <HttpStatusCode, TimeSpan>(), cache.Object)); // execute for different URLs await client.SendAsync(new HttpRequestMessage(method, "http://unittest1")); await client.SendAsync(new HttpRequestMessage(method, "http://unittest2")); // validate testMessageHandler.NumberOfCalls.Should().Be(2); cache.Verify(c => c.SetAsync(It.IsAny <string>(), It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); }
public async Task Gets_the_data_again_after_entry_is_gone_from_cache(HttpMethod method) { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync("http://unittest/", It.IsAny <CancellationToken>())).ReturnsAsync(default(byte[])); cache.Setup(c => c.SetAsync("http://unittest/", It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary <HttpStatusCode, TimeSpan>(), cache.Object)); // execute twice await client.SendAsync(new HttpRequestMessage(method, "http://unittest")); await client.SendAsync(new HttpRequestMessage(method, "http://unittest")); // validate testMessageHandler.NumberOfCalls.Should().Be(2); cache.Verify(c => c.GetAsync(method + "http://unittest/", It.IsAny <CancellationToken>()), Times.Exactly(2)); }
public async Task Caches_the_result() { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock<IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync("http://unittest/")).ReturnsAsync(null); cache.Setup(c => c.SetAsync("http://unittest/", It.IsAny<byte[]>(), It.IsAny<DistributedCacheEntryOptions>())).Returns(Task.FromResult(true)); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary<HttpStatusCode, TimeSpan>(), cache.Object)); // execute twice await client.GetAsync("http://unittest"); cache.Setup(c => c.GetAsync("http://unittest/")).ReturnsAsync(new SerializableCacheData(new byte[0], new HttpResponseMessage(HttpStatusCode.OK)).Serialize()); await client.GetAsync("http://unittest"); // validate testMessageHandler.NumberOfCalls.Should().Be(1); cache.Verify(c => c.GetAsync("http://unittest/"), Times.Exactly(2)); cache.Verify(c => c.SetAsync("http://unittest/", It.IsAny<byte[]>(), It.IsAny<DistributedCacheEntryOptions>()), Times.Once); }
public void Gets_the_underlying_data_on_get_error() { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync(HttpMethod.Get + "http://unittest/")).ThrowsAsync(new Exception("unittest")); cache.Setup(c => c.SetAsync(HttpMethod.Get + "http://unittest/", It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>())).Returns(Task.FromResult(true)); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary <HttpStatusCode, TimeSpan>(), cache.Object)); // execute Func <Task <HttpResponseMessage> > func = async() => await client.GetAsync("http://unittest"); func.ShouldNotThrow(); // validate testMessageHandler.NumberOfCalls.Should().Be(1); cache.Verify(c => c.GetAsync(HttpMethod.Get + "http://unittest/"), Times.Once); cache.Verify(c => c.SetAsync(HttpMethod.Get + "http://unittest/", It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>()), Times.Once); }
public void Ignores_set_cache_exceptions() { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync(HttpMethod.Get + "http://unittest/", default(CancellationToken))).ReturnsAsync(default(byte[])); cache.Setup(c => c.SetAsync(HttpMethod.Get + "http://unittest/", It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>(), It.IsAny <CancellationToken>())).Throws <Exception>(); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary <HttpStatusCode, TimeSpan>(), cache.Object)); // execute twice Func <Task <HttpResponseMessage> > func = async() => await client.GetAsync("http://unittest"); func.ShouldNotThrow(); // validate testMessageHandler.NumberOfCalls.Should().Be(1); cache.Verify(c => c.GetAsync(HttpMethod.Get + "http://unittest/", It.IsAny <CancellationToken>()), Times.Once); cache.Verify(c => c.SetAsync(HttpMethod.Get + "http://unittest/", It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>(), It.IsAny <CancellationToken>()), Times.Once); }
public async Task Caches_the_result(HttpMethod method) { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync(method + "http://unittest/", It.IsAny <CancellationToken>())).ReturnsAsync(default(byte[])); cache.Setup(c => c.SetAsync(method + "http://unittest/", It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary <HttpStatusCode, TimeSpan>(), cache.Object)); // execute twice await client.SendAsync(new HttpRequestMessage(method, "http://unittest")); cache.Setup(c => c.GetAsync(method + "http://unittest/", It.IsAny <CancellationToken>())).ReturnsAsync(() => new CacheData(new byte[0], new HttpResponseMessage(HttpStatusCode.OK), null, null).Serialize()); await client.SendAsync(new HttpRequestMessage(method, "http://unittest")); // validate testMessageHandler.NumberOfCalls.Should().Be(1); cache.Verify(c => c.GetAsync(method + "http://unittest/", It.IsAny <CancellationToken>()), Times.Exactly(2)); cache.Verify(c => c.SetAsync(method + "http://unittest/", It.IsAny <byte[]>(), It.IsAny <DistributedCacheEntryOptions>(), It.IsAny <CancellationToken>()), Times.Once); }
public async Task Only_caches_get_and_head_results() { // setup var testMessageHandler = new TestMessageHandler(); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary <HttpStatusCode, TimeSpan>(), (IDistributedCache)null)); // 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 void Invalidates_cache_per_method() { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock <IDistributedCache>(MockBehavior.Strict); var url = "http://unittest/"; var getKey = HttpMethod.Get + url; var headKey = HttpMethod.Head + url; cache.Setup(c => c.RemoveAsync(headKey, default(CancellationToken))).Returns(Task.FromResult(true)); cache.Setup(c => c.RemoveAsync(getKey, default(CancellationToken))).Throws <Exception>(); var cacheExpirationPerStatusCode = new Dictionary <HttpStatusCode, TimeSpan> { { (HttpStatusCode)200, TimeSpan.FromHours(1) } }; var handler = new RedisCacheHandler(testMessageHandler, cacheExpirationPerStatusCode, cache.Object); // execute Func <Task> func = async() => await handler.InvalidateCache(new Uri(url), HttpMethod.Head); // validate func.ShouldNotThrow(); cache.Verify(c => c.RemoveAsync(headKey, default(CancellationToken)), Times.Once); }
public async Task Data_from_call_matches_data_from_cache() { // setup var testMessageHandler = new TestMessageHandler(); var cache = new Mock<IDistributedCache>(MockBehavior.Strict); cache.Setup(c => c.GetAsync(It.IsAny<string>())).ReturnsAsync(new SerializableCacheData(Encoding.UTF8.GetBytes(TestMessageHandler.DefaultContent), new HttpResponseMessage(HttpStatusCode.OK)).Serialize()); cache.Setup(c => c.SetAsync(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<DistributedCacheEntryOptions>())).Returns(Task.FromResult(true)); var client = new HttpClient(new RedisCacheHandler(testMessageHandler, new Dictionary<HttpStatusCode, TimeSpan>(), cache.Object)); // 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); }