mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 20:12:51 +08:00
Merge pull request #109 from TomPallister/feature/clear-cache
Feature/clear cache
This commit is contained in:
commit
0139452fbf
@ -1,11 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ocelot.Cache
|
namespace Ocelot.Cache
|
||||||
{
|
{
|
||||||
public interface IOcelotCache<T>
|
public interface IOcelotCache<T>
|
||||||
{
|
{
|
||||||
void Add(string key, T value, TimeSpan ttl);
|
void Add(string key, T value, TimeSpan ttl, string region);
|
||||||
void AddAndDelete(string key, T value, TimeSpan ttl);
|
void AddAndDelete(string key, T value, TimeSpan ttl, string region);
|
||||||
T Get(string key);
|
T Get(string key, string region);
|
||||||
|
void ClearRegion(string region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
src/Ocelot/Cache/IRegionCreator.cs
Normal file
9
src/Ocelot/Cache/IRegionCreator.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using Ocelot.Configuration.File;
|
||||||
|
|
||||||
|
namespace Ocelot.Cache
|
||||||
|
{
|
||||||
|
public interface IRegionCreator
|
||||||
|
{
|
||||||
|
string Create(FileReRoute reRoute);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
@ -13,16 +14,19 @@ namespace Ocelot.Cache.Middleware
|
|||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IOcelotLogger _logger;
|
private readonly IOcelotLogger _logger;
|
||||||
private readonly IOcelotCache<HttpResponseMessage> _outputCache;
|
private readonly IOcelotCache<HttpResponseMessage> _outputCache;
|
||||||
|
private readonly IRegionCreator _regionCreator;
|
||||||
|
|
||||||
public OutputCacheMiddleware(RequestDelegate next,
|
public OutputCacheMiddleware(RequestDelegate next,
|
||||||
IOcelotLoggerFactory loggerFactory,
|
IOcelotLoggerFactory loggerFactory,
|
||||||
IRequestScopedDataRepository scopedDataRepository,
|
IRequestScopedDataRepository scopedDataRepository,
|
||||||
IOcelotCache<HttpResponseMessage> outputCache)
|
IOcelotCache<HttpResponseMessage> outputCache,
|
||||||
|
IRegionCreator regionCreator)
|
||||||
:base(scopedDataRepository)
|
:base(scopedDataRepository)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_outputCache = outputCache;
|
_outputCache = outputCache;
|
||||||
_logger = loggerFactory.CreateLogger<OutputCacheMiddleware>();
|
_logger = loggerFactory.CreateLogger<OutputCacheMiddleware>();
|
||||||
|
_regionCreator = regionCreator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
@ -33,11 +37,11 @@ namespace Ocelot.Cache.Middleware
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var downstreamUrlKey = DownstreamRequest.RequestUri.OriginalString;
|
var downstreamUrlKey = $"{DownstreamRequest.Method.Method}-{DownstreamRequest.RequestUri.OriginalString}";
|
||||||
|
|
||||||
_logger.LogDebug("started checking cache for {downstreamUrlKey}", downstreamUrlKey);
|
_logger.LogDebug("started checking cache for {downstreamUrlKey}", downstreamUrlKey);
|
||||||
|
|
||||||
var cached = _outputCache.Get(downstreamUrlKey);
|
var cached = _outputCache.Get(downstreamUrlKey, DownstreamRoute.ReRoute.CacheOptions.Region);
|
||||||
|
|
||||||
if (cached != null)
|
if (cached != null)
|
||||||
{
|
{
|
||||||
@ -63,7 +67,7 @@ namespace Ocelot.Cache.Middleware
|
|||||||
|
|
||||||
var response = HttpResponseMessage;
|
var response = HttpResponseMessage;
|
||||||
|
|
||||||
_outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.FileCacheOptions.TtlSeconds));
|
_outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.CacheOptions.TtlSeconds), DownstreamRoute.ReRoute.CacheOptions.Region);
|
||||||
|
|
||||||
_logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey);
|
_logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using CacheManager.Core;
|
using CacheManager.Core;
|
||||||
|
|
||||||
namespace Ocelot.Cache
|
namespace Ocelot.Cache
|
||||||
@ -12,12 +14,12 @@ namespace Ocelot.Cache
|
|||||||
_cacheManager = cacheManager;
|
_cacheManager = cacheManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(string key, T value, TimeSpan ttl)
|
public void Add(string key, T value, TimeSpan ttl, string region)
|
||||||
{
|
{
|
||||||
_cacheManager.Add(new CacheItem<T>(key, value, ExpirationMode.Absolute, ttl));
|
_cacheManager.Add(new CacheItem<T>(key, region, value, ExpirationMode.Absolute, ttl));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddAndDelete(string key, T value, TimeSpan ttl)
|
public void AddAndDelete(string key, T value, TimeSpan ttl, string region)
|
||||||
{
|
{
|
||||||
var exists = _cacheManager.Get(key);
|
var exists = _cacheManager.Get(key);
|
||||||
|
|
||||||
@ -26,12 +28,17 @@ namespace Ocelot.Cache
|
|||||||
_cacheManager.Remove(key);
|
_cacheManager.Remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cacheManager.Add(new CacheItem<T>(key, value, ExpirationMode.Absolute, ttl));
|
Add(key, value, ttl, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T Get(string key)
|
public T Get(string key, string region)
|
||||||
{
|
{
|
||||||
return _cacheManager.Get<T>(key);
|
return _cacheManager.Get<T>(key, region);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearRegion(string region)
|
||||||
|
{
|
||||||
|
_cacheManager.ClearRegion(region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
24
src/Ocelot/Cache/RegionCreator.cs
Normal file
24
src/Ocelot/Cache/RegionCreator.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
|
||||||
|
namespace Ocelot.Cache
|
||||||
|
{
|
||||||
|
|
||||||
|
public class RegionCreator : IRegionCreator
|
||||||
|
{
|
||||||
|
public string Create(FileReRoute reRoute)
|
||||||
|
{
|
||||||
|
if(!string.IsNullOrEmpty(reRoute?.FileCacheOptions?.Region))
|
||||||
|
{
|
||||||
|
return reRoute?.FileCacheOptions?.Region;
|
||||||
|
}
|
||||||
|
|
||||||
|
var methods = string.Join("", reRoute.UpstreamHttpMethod.Select(m => m));
|
||||||
|
|
||||||
|
var region = $"{methods}{reRoute.UpstreamPathTemplate.Replace("/", "")}";
|
||||||
|
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/Ocelot/Cache/Regions.cs
Normal file
13
src/Ocelot/Cache/Regions.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ocelot.Cache
|
||||||
|
{
|
||||||
|
public class Regions
|
||||||
|
{
|
||||||
|
public Regions(List<string> value)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
public List<string> Value {get;private set;}
|
||||||
|
}
|
||||||
|
}
|
@ -2,11 +2,13 @@
|
|||||||
{
|
{
|
||||||
public class CacheOptions
|
public class CacheOptions
|
||||||
{
|
{
|
||||||
public CacheOptions(int ttlSeconds)
|
public CacheOptions(int ttlSeconds, string region)
|
||||||
{
|
{
|
||||||
TtlSeconds = ttlSeconds;
|
TtlSeconds = ttlSeconds;
|
||||||
|
Region = region;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int TtlSeconds { get; private set; }
|
public int TtlSeconds { get; private set; }
|
||||||
|
public string Region {get;private set;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Ocelot.Cache;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.Configuration.File;
|
using Ocelot.Configuration.File;
|
||||||
using Ocelot.Configuration.Parser;
|
using Ocelot.Configuration.Parser;
|
||||||
@ -36,6 +37,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
private IQoSOptionsCreator _qosOptionsCreator;
|
private IQoSOptionsCreator _qosOptionsCreator;
|
||||||
private IReRouteOptionsCreator _fileReRouteOptionsCreator;
|
private IReRouteOptionsCreator _fileReRouteOptionsCreator;
|
||||||
private IRateLimitOptionsCreator _rateLimitOptionsCreator;
|
private IRateLimitOptionsCreator _rateLimitOptionsCreator;
|
||||||
|
private IRegionCreator _regionCreator;
|
||||||
|
|
||||||
public FileOcelotConfigurationCreator(
|
public FileOcelotConfigurationCreator(
|
||||||
IOptions<FileConfiguration> options,
|
IOptions<FileConfiguration> options,
|
||||||
@ -52,9 +54,11 @@ namespace Ocelot.Configuration.Creator
|
|||||||
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
|
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
|
||||||
IQoSOptionsCreator qosOptionsCreator,
|
IQoSOptionsCreator qosOptionsCreator,
|
||||||
IReRouteOptionsCreator fileReRouteOptionsCreator,
|
IReRouteOptionsCreator fileReRouteOptionsCreator,
|
||||||
IRateLimitOptionsCreator rateLimitOptionsCreator
|
IRateLimitOptionsCreator rateLimitOptionsCreator,
|
||||||
|
IRegionCreator regionCreator
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
_regionCreator = regionCreator;
|
||||||
_rateLimitOptionsCreator = rateLimitOptionsCreator;
|
_rateLimitOptionsCreator = rateLimitOptionsCreator;
|
||||||
_requestIdKeyCreator = requestIdKeyCreator;
|
_requestIdKeyCreator = requestIdKeyCreator;
|
||||||
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
|
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
|
||||||
@ -137,6 +141,8 @@ namespace Ocelot.Configuration.Creator
|
|||||||
|
|
||||||
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
|
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
|
||||||
|
|
||||||
|
var region = _regionCreator.Create(fileReRoute);
|
||||||
|
|
||||||
var reRoute = new ReRouteBuilder()
|
var reRoute = new ReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
|
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
|
||||||
.WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
|
.WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
|
||||||
@ -151,7 +157,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
.WithClaimsToQueries(claimsToQueries)
|
.WithClaimsToQueries(claimsToQueries)
|
||||||
.WithRequestIdKey(requestIdKey)
|
.WithRequestIdKey(requestIdKey)
|
||||||
.WithIsCached(fileReRouteOptions.IsCached)
|
.WithIsCached(fileReRouteOptions.IsCached)
|
||||||
.WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds))
|
.WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds, region))
|
||||||
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
|
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
|
||||||
.WithLoadBalancer(fileReRoute.LoadBalancer)
|
.WithLoadBalancer(fileReRoute.LoadBalancer)
|
||||||
.WithDownstreamHost(fileReRoute.DownstreamHost)
|
.WithDownstreamHost(fileReRoute.DownstreamHost)
|
||||||
|
@ -3,5 +3,6 @@
|
|||||||
public class FileCacheOptions
|
public class FileCacheOptions
|
||||||
{
|
{
|
||||||
public int TtlSeconds { get; set; }
|
public int TtlSeconds { get; set; }
|
||||||
|
public string Region {get; set;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ namespace Ocelot.Configuration
|
|||||||
IsAuthorised = isAuthorised;
|
IsAuthorised = isAuthorised;
|
||||||
RequestIdKey = requestIdKey;
|
RequestIdKey = requestIdKey;
|
||||||
IsCached = isCached;
|
IsCached = isCached;
|
||||||
FileCacheOptions = fileCacheOptions;
|
CacheOptions = fileCacheOptions;
|
||||||
ClaimsToQueries = claimsToQueries
|
ClaimsToQueries = claimsToQueries
|
||||||
?? new List<ClaimToThing>();
|
?? new List<ClaimToThing>();
|
||||||
ClaimsToClaims = claimsToClaims
|
ClaimsToClaims = claimsToClaims
|
||||||
@ -74,7 +74,7 @@ namespace Ocelot.Configuration
|
|||||||
public Dictionary<string, string> RouteClaimsRequirement { get; private set; }
|
public Dictionary<string, string> RouteClaimsRequirement { get; private set; }
|
||||||
public string RequestIdKey { get; private set; }
|
public string RequestIdKey { get; private set; }
|
||||||
public bool IsCached { get; private set; }
|
public bool IsCached { get; private set; }
|
||||||
public CacheOptions FileCacheOptions { get; private set; }
|
public CacheOptions CacheOptions { get; private set; }
|
||||||
public string DownstreamScheme {get;private set;}
|
public string DownstreamScheme {get;private set;}
|
||||||
public bool IsQos { get; private set; }
|
public bool IsQos { get; private set; }
|
||||||
public QoSOptions QosOptionsOptions { get; private set; }
|
public QoSOptions QosOptionsOptions { get; private set; }
|
||||||
|
@ -30,7 +30,7 @@ namespace Ocelot.Configuration.Repository
|
|||||||
|
|
||||||
public async Task<Response<IOcelotConfiguration>> Get()
|
public async Task<Response<IOcelotConfiguration>> Get()
|
||||||
{
|
{
|
||||||
var config = _cache.Get(_ocelotConfiguration);
|
var config = _cache.Get(_ocelotConfiguration, _ocelotConfiguration);
|
||||||
|
|
||||||
if (config != null)
|
if (config != null)
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ namespace Ocelot.Configuration.Repository
|
|||||||
|
|
||||||
if (result.Response)
|
if (result.Response)
|
||||||
{
|
{
|
||||||
_cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3));
|
_cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), _ocelotConfiguration);
|
||||||
|
|
||||||
return new OkResponse();
|
return new OkResponse();
|
||||||
}
|
}
|
||||||
|
29
src/Ocelot/Controllers/OutputCacheController.cs
Normal file
29
src/Ocelot/Controllers/OutputCacheController.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Ocelot.Cache;
|
||||||
|
using Ocelot.Configuration.Provider;
|
||||||
|
|
||||||
|
namespace Ocelot.Controllers
|
||||||
|
{
|
||||||
|
[Authorize]
|
||||||
|
[Route("outputcache")]
|
||||||
|
public class OutputCacheController : Controller
|
||||||
|
{
|
||||||
|
private IOcelotCache<HttpResponseMessage> _cache;
|
||||||
|
|
||||||
|
public OutputCacheController(IOcelotCache<HttpResponseMessage> cache)
|
||||||
|
{
|
||||||
|
_cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete]
|
||||||
|
[Route("{region}")]
|
||||||
|
public IActionResult Delete(string region)
|
||||||
|
{
|
||||||
|
_cache.ClearRegion(region);
|
||||||
|
return new NoContentResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -145,6 +145,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
.AddJsonFormatters();
|
.AddJsonFormatters();
|
||||||
|
|
||||||
services.AddLogging();
|
services.AddLogging();
|
||||||
|
services.TryAddSingleton<IRegionCreator, RegionCreator>();
|
||||||
services.TryAddSingleton<IFileConfigurationRepository, FileConfigurationRepository>();
|
services.TryAddSingleton<IFileConfigurationRepository, FileConfigurationRepository>();
|
||||||
services.TryAddSingleton<IFileConfigurationSetter, FileConfigurationSetter>();
|
services.TryAddSingleton<IFileConfigurationSetter, FileConfigurationSetter>();
|
||||||
services.TryAddSingleton<IFileConfigurationProvider, FileConfigurationProvider>();
|
services.TryAddSingleton<IFileConfigurationProvider, FileConfigurationProvider>();
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
||||||
|
@ -7,6 +7,7 @@ using System.Net.Http.Headers;
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Ocelot.Cache;
|
||||||
using Ocelot.Configuration.File;
|
using Ocelot.Configuration.File;
|
||||||
using Ocelot.ManualTest;
|
using Ocelot.ManualTest;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
@ -120,7 +121,12 @@ namespace Ocelot.IntegrationTests
|
|||||||
DownstreamScheme = "https",
|
DownstreamScheme = "https",
|
||||||
DownstreamPathTemplate = "/",
|
DownstreamPathTemplate = "/",
|
||||||
UpstreamHttpMethod = new List<string> { "get" },
|
UpstreamHttpMethod = new List<string> { "get" },
|
||||||
UpstreamPathTemplate = "/"
|
UpstreamPathTemplate = "/",
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
TtlSeconds = 10,
|
||||||
|
Region = "Geoff"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
new FileReRoute()
|
new FileReRoute()
|
||||||
{
|
{
|
||||||
@ -129,7 +135,12 @@ namespace Ocelot.IntegrationTests
|
|||||||
DownstreamScheme = "https",
|
DownstreamScheme = "https",
|
||||||
DownstreamPathTemplate = "/",
|
DownstreamPathTemplate = "/",
|
||||||
UpstreamHttpMethod = new List<string> { "get" },
|
UpstreamHttpMethod = new List<string> { "get" },
|
||||||
UpstreamPathTemplate = "/test"
|
UpstreamPathTemplate = "/test",
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
TtlSeconds = 10,
|
||||||
|
Region = "Dave"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -218,6 +229,57 @@ namespace Ocelot.IntegrationTests
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_clear_region()
|
||||||
|
{
|
||||||
|
var initialConfiguration = new FileConfiguration
|
||||||
|
{
|
||||||
|
GlobalConfiguration = new FileGlobalConfiguration
|
||||||
|
{
|
||||||
|
AdministrationPath = "/administration"
|
||||||
|
},
|
||||||
|
ReRoutes = new List<FileReRoute>()
|
||||||
|
{
|
||||||
|
new FileReRoute()
|
||||||
|
{
|
||||||
|
DownstreamHost = "localhost",
|
||||||
|
DownstreamPort = 80,
|
||||||
|
DownstreamScheme = "https",
|
||||||
|
DownstreamPathTemplate = "/",
|
||||||
|
UpstreamHttpMethod = new List<string> { "get" },
|
||||||
|
UpstreamPathTemplate = "/",
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
TtlSeconds = 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new FileReRoute()
|
||||||
|
{
|
||||||
|
DownstreamHost = "localhost",
|
||||||
|
DownstreamPort = 80,
|
||||||
|
DownstreamScheme = "https",
|
||||||
|
DownstreamPathTemplate = "/",
|
||||||
|
UpstreamHttpMethod = new List<string> { "get" },
|
||||||
|
UpstreamPathTemplate = "/test",
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
TtlSeconds = 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var regionToClear = "gettest";
|
||||||
|
|
||||||
|
this.Given(x => GivenThereIsAConfiguration(initialConfiguration))
|
||||||
|
.And(x => GivenOcelotIsRunning())
|
||||||
|
.And(x => GivenIHaveAnOcelotToken("/administration"))
|
||||||
|
.And(x => GivenIHaveAddedATokenToMyRequest())
|
||||||
|
.When(x => WhenIDeleteOnTheApiGateway($"/administration/outputcache/{regionToClear}"))
|
||||||
|
.Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.NoContent))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenAnotherOcelotIsRunning(string baseUrl)
|
private void GivenAnotherOcelotIsRunning(string baseUrl)
|
||||||
{
|
{
|
||||||
_httpClientTwo.BaseAddress = new Uri(baseUrl);
|
_httpClientTwo.BaseAddress = new Uri(baseUrl);
|
||||||
@ -256,6 +318,13 @@ namespace Ocelot.IntegrationTests
|
|||||||
_response = _httpClient.PostAsync(url, content).Result;
|
_response = _httpClient.PostAsync(url, content).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheResponseShouldBe(List<string> expected)
|
||||||
|
{
|
||||||
|
var content = _response.Content.ReadAsStringAsync().Result;
|
||||||
|
var result = JsonConvert.DeserializeObject<Regions>(content);
|
||||||
|
result.Value.ShouldBe(expected);
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheResponseShouldBe(FileConfiguration expected)
|
private void ThenTheResponseShouldBe(FileConfiguration expected)
|
||||||
{
|
{
|
||||||
var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
|
var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
|
||||||
@ -353,6 +422,11 @@ namespace Ocelot.IntegrationTests
|
|||||||
_response = _httpClient.GetAsync(url).Result;
|
_response = _httpClient.GetAsync(url).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WhenIDeleteOnTheApiGateway(string url)
|
||||||
|
{
|
||||||
|
_response = _httpClient.DeleteAsync(url).Result;
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode)
|
private void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode)
|
||||||
{
|
{
|
||||||
_response.StatusCode.ShouldBe(expectedHttpStatusCode);
|
_response.StatusCode.ShouldBe(expectedHttpStatusCode);
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Http" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using CacheManager.Core;
|
using CacheManager.Core;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Cache;
|
using Ocelot.Cache;
|
||||||
@ -16,20 +17,22 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
private string _value;
|
private string _value;
|
||||||
private string _resultGet;
|
private string _resultGet;
|
||||||
private TimeSpan _ttlSeconds;
|
private TimeSpan _ttlSeconds;
|
||||||
|
private List<string> _resultKeys;
|
||||||
|
private string _region;
|
||||||
|
|
||||||
public CacheManagerCacheTests()
|
public CacheManagerCacheTests()
|
||||||
{
|
{
|
||||||
_mockCacheManager = new Mock<ICacheManager<string>>();
|
_mockCacheManager = new Mock<ICacheManager<string>>();
|
||||||
_ocelotOcelotCacheManager = new OcelotCacheManagerCache<string>(_mockCacheManager.Object);
|
_ocelotOcelotCacheManager = new OcelotCacheManagerCache<string>(_mockCacheManager.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_get_from_cache()
|
public void should_get_from_cache()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenTheFollowingIsCached("someKey", "someValue"))
|
this.Given(x => x.GivenTheFollowingIsCached("someKey", "someRegion", "someValue"))
|
||||||
.When(x => x.WhenIGetFromTheCache())
|
.When(x => x.WhenIGetFromTheCache())
|
||||||
.Then(x => x.ThenTheResultIs("someValue"))
|
.Then(x => x.ThenTheResultIs("someValue"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -40,13 +43,37 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_delete_key_from_cache()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheFollowingRegion("fookey"))
|
||||||
|
.When(_ => WhenIDeleteTheRegion("fookey"))
|
||||||
|
.Then(_ => ThenTheRegionIsDeleted("fookey"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIDeleteTheRegion(string region)
|
||||||
|
{
|
||||||
|
_ocelotOcelotCacheManager.ClearRegion(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheRegionIsDeleted(string region)
|
||||||
|
{
|
||||||
|
_mockCacheManager
|
||||||
|
.Verify(x => x.ClearRegion(region), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheFollowingRegion(string key)
|
||||||
|
{
|
||||||
|
_ocelotOcelotCacheManager.Add(key, "doesnt matter", TimeSpan.FromSeconds(10), "region");
|
||||||
|
}
|
||||||
|
|
||||||
private void WhenIAddToTheCache(string key, string value, TimeSpan ttlSeconds)
|
private void WhenIAddToTheCache(string key, string value, TimeSpan ttlSeconds)
|
||||||
{
|
{
|
||||||
_key = key;
|
_key = key;
|
||||||
_value = value;
|
_value = value;
|
||||||
_ttlSeconds = ttlSeconds;
|
_ttlSeconds = ttlSeconds;
|
||||||
|
_ocelotOcelotCacheManager.Add(_key, _value, _ttlSeconds, "region");
|
||||||
_ocelotOcelotCacheManager.Add(_key, _value, _ttlSeconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheCacheIsCalledCorrectly()
|
private void ThenTheCacheIsCalledCorrectly()
|
||||||
@ -62,15 +89,16 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
|
|
||||||
private void WhenIGetFromTheCache()
|
private void WhenIGetFromTheCache()
|
||||||
{
|
{
|
||||||
_resultGet = _ocelotOcelotCacheManager.Get(_key);
|
_resultGet = _ocelotOcelotCacheManager.Get(_key, _region);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheFollowingIsCached(string key, string value)
|
private void GivenTheFollowingIsCached(string key, string region, string value)
|
||||||
{
|
{
|
||||||
_key = key;
|
_key = key;
|
||||||
_value = value;
|
_value = value;
|
||||||
|
_region = region;
|
||||||
_mockCacheManager
|
_mockCacheManager
|
||||||
.Setup(x => x.Get<string>(It.IsAny<string>()))
|
.Setup(x => x.Get<string>(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Returns(value);
|
.Returns(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Net.Http;
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
using Microsoft.AspNetCore.TestHost;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Cache;
|
using Ocelot.Cache;
|
||||||
using Ocelot.Cache.Middleware;
|
using Ocelot.Cache.Middleware;
|
||||||
@ -43,6 +44,7 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
x.AddLogging();
|
x.AddLogging();
|
||||||
x.AddSingleton(_cacheManager.Object);
|
x.AddSingleton(_cacheManager.Object);
|
||||||
x.AddSingleton(_scopedRepo.Object);
|
x.AddSingleton(_scopedRepo.Object);
|
||||||
|
x.AddSingleton<IRegionCreator, RegionCreator>();
|
||||||
})
|
})
|
||||||
.UseUrls(_url)
|
.UseUrls(_url)
|
||||||
.UseKestrel()
|
.UseKestrel()
|
||||||
@ -90,7 +92,7 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
{
|
{
|
||||||
var reRoute = new ReRouteBuilder()
|
var reRoute = new ReRouteBuilder()
|
||||||
.WithIsCached(true)
|
.WithIsCached(true)
|
||||||
.WithCacheOptions(new CacheOptions(100))
|
.WithCacheOptions(new CacheOptions(100, "kanken"))
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -118,13 +120,13 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
private void ThenTheCacheGetIsCalledCorrectly()
|
private void ThenTheCacheGetIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_cacheManager
|
_cacheManager
|
||||||
.Verify(x => x.Get(It.IsAny<string>()), Times.Once);
|
.Verify(x => x.Get(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheCacheAddIsCalledCorrectly()
|
private void ThenTheCacheAddIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_cacheManager
|
_cacheManager
|
||||||
.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<HttpResponseMessage>(), It.IsAny<TimeSpan>()), Times.Once);
|
.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<HttpResponseMessage>(), It.IsAny<TimeSpan>(), It.IsAny<string>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenResponseIsNotCached()
|
private void GivenResponseIsNotCached()
|
||||||
@ -138,7 +140,7 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
{
|
{
|
||||||
_response = response;
|
_response = response;
|
||||||
_cacheManager
|
_cacheManager
|
||||||
.Setup(x => x.Get(It.IsAny<string>()))
|
.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Returns(_response);
|
.Returns(_response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
65
test/Ocelot.UnitTests/Cache/RegionCreatorTests.cs
Normal file
65
test/Ocelot.UnitTests/Cache/RegionCreatorTests.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Ocelot.Cache;
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Cache
|
||||||
|
{
|
||||||
|
public class RegionCreatorTests
|
||||||
|
{
|
||||||
|
private string _result;
|
||||||
|
private FileReRoute _reRoute;
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_region()
|
||||||
|
{
|
||||||
|
var reRoute = new FileReRoute
|
||||||
|
{
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
UpstreamPathTemplate = "/testdummy"
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheReRoute(reRoute))
|
||||||
|
.When(_ => WhenICreateTheRegion())
|
||||||
|
.Then(_ => ThenTheRegionIs("Gettestdummy"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_use_region()
|
||||||
|
{
|
||||||
|
var reRoute = new FileReRoute
|
||||||
|
{
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
Region = "region"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheReRoute(reRoute))
|
||||||
|
.When(_ => WhenICreateTheRegion())
|
||||||
|
.Then(_ => ThenTheRegionIs("region"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheReRoute(FileReRoute reRoute)
|
||||||
|
{
|
||||||
|
_reRoute = reRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenICreateTheRegion()
|
||||||
|
{
|
||||||
|
RegionCreator regionCreator = new RegionCreator();
|
||||||
|
_result = regionCreator.Create(_reRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheRegionIs(string expected)
|
||||||
|
{
|
||||||
|
_result.ShouldBe(expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
using Ocelot.Cache;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.Configuration.Creator;
|
using Ocelot.Configuration.Creator;
|
||||||
@ -39,6 +40,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
||||||
private Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator;
|
private Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator;
|
||||||
private Mock<IRateLimitOptionsCreator> _rateLimitOptions;
|
private Mock<IRateLimitOptionsCreator> _rateLimitOptions;
|
||||||
|
private Mock<IRegionCreator> _regionCreator;
|
||||||
|
|
||||||
public FileConfigurationCreatorTests()
|
public FileConfigurationCreatorTests()
|
||||||
{
|
{
|
||||||
@ -59,6 +61,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
_qosOptionsCreator = new Mock<IQoSOptionsCreator>();
|
_qosOptionsCreator = new Mock<IQoSOptionsCreator>();
|
||||||
_fileReRouteOptionsCreator = new Mock<IReRouteOptionsCreator>();
|
_fileReRouteOptionsCreator = new Mock<IReRouteOptionsCreator>();
|
||||||
_rateLimitOptions = new Mock<IRateLimitOptionsCreator>();
|
_rateLimitOptions = new Mock<IRateLimitOptionsCreator>();
|
||||||
|
_regionCreator = new Mock<IRegionCreator>();
|
||||||
|
|
||||||
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
|
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
|
||||||
_fileConfig.Object, _validator.Object, _logger.Object,
|
_fileConfig.Object, _validator.Object, _logger.Object,
|
||||||
@ -66,7 +69,51 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
_qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object,
|
_qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object,
|
||||||
_authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object,
|
_authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object,
|
||||||
_serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object,
|
_serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object,
|
||||||
_rateLimitOptions.Object);
|
_rateLimitOptions.Object, _regionCreator.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_call_region_creator()
|
||||||
|
{
|
||||||
|
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamHost = "127.0.0.1",
|
||||||
|
UpstreamPathTemplate = "/api/products/{productId}",
|
||||||
|
DownstreamPathTemplate = "/products/{productId}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
Region = "region"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||||
|
.And(x => x.GivenTheConfigIsValid())
|
||||||
|
.And(x => x.GivenTheFollowingRegionIsReturned("region"))
|
||||||
|
.When(x => x.WhenICreateTheConfig())
|
||||||
|
.Then(x => x.ThenTheRegionCreatorIsCalledCorrectly("region"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheFollowingRegionIsReturned(string region)
|
||||||
|
{
|
||||||
|
_regionCreator
|
||||||
|
.Setup(x => x.Create(It.IsAny<FileReRoute>()))
|
||||||
|
.Returns(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheRegionCreatorIsCalledCorrectly(string expected)
|
||||||
|
{
|
||||||
|
_regionCreator
|
||||||
|
.Verify(x => x.Create(_fileConfiguration.ReRoutes[0]), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
using Xunit;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Ocelot.Controllers;
|
||||||
|
using System;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Cache;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Controllers
|
||||||
|
{
|
||||||
|
public class OutputCacheControllerTests
|
||||||
|
{
|
||||||
|
private OutputCacheController _controller;
|
||||||
|
private Mock<IOcelotCache<HttpResponseMessage>> _cache;
|
||||||
|
private IActionResult _result;
|
||||||
|
|
||||||
|
public OutputCacheControllerTests()
|
||||||
|
{
|
||||||
|
_cache = new Mock<IOcelotCache<HttpResponseMessage>>();
|
||||||
|
_controller = new OutputCacheController(_cache.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_delete_key()
|
||||||
|
{
|
||||||
|
this.When(_ => WhenIDeleteTheKey("a"))
|
||||||
|
.Then(_ => ThenTheKeyIsDeleted("a"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheKeyIsDeleted(string key)
|
||||||
|
{
|
||||||
|
_result.ShouldBeOfType<NoContentResult>();
|
||||||
|
_cache
|
||||||
|
.Verify(x => x.ClearRegion(key), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIDeleteTheKey(string key)
|
||||||
|
{
|
||||||
|
_result = _controller.Delete(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user