unit tests for cache clearing passing

This commit is contained in:
Tom Gardham-Pallister 2017-06-27 18:54:15 +01:00
parent 239dcfb6bd
commit e4e7fcc943
10 changed files with 244 additions and 5 deletions

View File

@ -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)
@ -63,7 +67,7 @@ namespace Ocelot.Cache.Middleware
var response = HttpResponseMessage; var response = HttpResponseMessage;
var region = $"{DownstreamRoute.ReRoute.UpstreamHttpMethod}-{DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}"; var region = _regionCreator.Region(DownstreamRoute.ReRoute);
_outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.FileCacheOptions.TtlSeconds), region); _outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.FileCacheOptions.TtlSeconds), region);

View File

@ -0,0 +1,22 @@
using System.Linq;
using Ocelot.Configuration;
namespace Ocelot.Cache
{
public interface IRegionCreator
{
string Region(ReRoute reRoute);
}
public class RegionCreator : IRegionCreator
{
public string Region(ReRoute reRoute)
{
var methods = string.Join(",", reRoute.UpstreamHttpMethod.Select(m => m.Method));
var region = $"{methods} {reRoute.UpstreamPathTemplate.Value}";
return region;
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ocelot.Configuration.Provider;
using Ocelot.Logging;
namespace Ocelot.Cache
{
public interface IRegionsGetter
{
Task<List<string>> Regions();
}
public class RegionsGetter : IRegionsGetter
{
private readonly IOcelotConfigurationProvider _provider;
private readonly IRegionCreator _creator;
private readonly IOcelotLogger _logger;
public RegionsGetter(IOcelotConfigurationProvider provider, IRegionCreator creator, IOcelotLoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<RegionsGetter>();
_provider = provider;
_creator = creator;
}
public async Task<List<string>> Regions()
{
var config = await _provider.Get();
if(config.IsError)
{
_logger.LogError("unable to find regions", new Exception(string.Join(",", config.Errors)));
return new List<string>();
}
var regions = new List<string>();
foreach(var reRoute in config.Data.ReRoutes)
{
var region = _creator.Region(reRoute);
regions.Add(region);
}
return regions;
}
}
}

View File

@ -2,6 +2,7 @@ using System.Net.Http;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Ocelot.Cache; using Ocelot.Cache;
using Ocelot.Configuration.Provider;
namespace Ocelot.Controllers namespace Ocelot.Controllers
{ {
@ -10,16 +11,19 @@ namespace Ocelot.Controllers
public class OutputCacheController : Controller public class OutputCacheController : Controller
{ {
private IOcelotCache<HttpResponseMessage> _cache; private IOcelotCache<HttpResponseMessage> _cache;
private IRegionsGetter _regionsGetter;
public OutputCacheController(IOcelotCache<HttpResponseMessage> cache) public OutputCacheController(IOcelotCache<HttpResponseMessage> cache, IRegionsGetter regionsGetter)
{ {
_cache = cache; _cache = cache;
_regionsGetter = regionsGetter;
} }
[HttpGet] [HttpGet]
public IActionResult Get() public IActionResult Get()
{ {
return new NotFoundResult(); var regions = _regionsGetter.Regions();
return new OkObjectResult(regions);
} }
[HttpDelete] [HttpDelete]

View File

@ -145,6 +145,8 @@ namespace Ocelot.DependencyInjection
.AddJsonFormatters(); .AddJsonFormatters();
services.AddLogging(); services.AddLogging();
services.TryAddSingleton<IRegionsGetter, RegionsGetter>();
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>();

View File

@ -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" />

View File

@ -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()

View File

@ -0,0 +1,46 @@
using System.Collections.Generic;
using Ocelot.Cache;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.UnitTests.Cache
{
public class RegionCreatorTests
{
private string _result;
private ReRoute _reRoute;
[Fact]
public void should_create_region()
{
var reRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod(new List<string>{"Get"})
.WithUpstreamPathTemplate("/test/dummy")
.Build();
this.Given(_ => GivenTheReRoute(reRoute))
.When(_ => WhenICreateTheRegion())
.Then(_ => ThenTheRegionIs("Get /test/dummy"))
.BDDfy();
}
private void GivenTheReRoute(ReRoute reRoute)
{
_reRoute = reRoute;
}
private void WhenICreateTheRegion()
{
RegionCreator regionCreator = new RegionCreator();
_result = regionCreator.Region(_reRoute);
}
private void ThenTheRegionIs(string expected)
{
_result.ShouldBe(expected);
}
}
}

View File

@ -0,0 +1,109 @@
using Xunit;
using TestStack.BDDfy;
using Shouldly;
using Ocelot.Cache;
using Moq;
using Ocelot.Configuration.Provider;
using System.Collections.Generic;
using Ocelot.Responses;
using Ocelot.Configuration;
using System.Threading.Tasks;
using Ocelot.Configuration.Builder;
using System;
using Ocelot.Errors;
using Ocelot.Logging;
namespace Ocelot.UnitTests.Cache
{
public class RegionsGetterTests
{
private RegionsGetter _regionsGetter;
private readonly Mock<IOcelotConfigurationProvider> _provider;
private readonly Mock<IRegionCreator> _creator;
private readonly Mock<IOcelotLoggerFactory> _factory;
private List<string> _result;
public RegionsGetterTests()
{
_provider = new Mock<IOcelotConfigurationProvider>();
_creator = new Mock<IRegionCreator>();
_factory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_factory
.Setup(x => x.CreateLogger<RegionsGetter>())
.Returns(logger.Object);
_regionsGetter = new RegionsGetter(_provider.Object, _creator.Object, _factory.Object);
}
[Fact]
public void should_get_regions()
{
var reRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod(new List<string>{"Get"})
.WithUpstreamPathTemplate("/")
.Build();
var reRoutes = new List<ReRoute>
{
reRoute
};
var config = new OcelotConfiguration(reRoutes, "whocares!");
var expected = new List<string>
{
"balls"
};
this.Given(_ => GivenTheFollowingConfig(config))
.And(_ => GivenTheProviderReturns("balls"))
.When(_ => WhenIGetTheRegions())
.Then(_ => ThenTheFollowingIsReturned(expected))
.BDDfy();
}
[Fact]
public void should_return_empty_regions()
{
var expected = new List<string>();
this.Given(_ => GivenAnErrorGettingTheConfig())
.When(_ => WhenIGetTheRegions())
.Then(_ => ThenTheFollowingIsReturned(expected))
.BDDfy();
}
private void GivenAnErrorGettingTheConfig()
{
var config = new OcelotConfiguration(new List<ReRoute>(), "whocares!");
_provider
.Setup(x => x.Get())
.ReturnsAsync(new ErrorResponse<IOcelotConfiguration>(It.IsAny<Error>()));
}
private void GivenTheProviderReturns(string expected)
{
_creator
.Setup(x => x.Region(It.IsAny<ReRoute>()))
.Returns(expected);
}
private void GivenTheFollowingConfig(IOcelotConfiguration config)
{
_provider
.Setup(x => x.Get())
.ReturnsAsync(new OkResponse<IOcelotConfiguration>(config));
}
private void WhenIGetTheRegions()
{
_result = _regionsGetter.Regions().Result;
}
private void ThenTheFollowingIsReturned(List<string> expected)
{
_result.ShouldBe(expected);
}
}
}

View File

@ -15,12 +15,14 @@ namespace Ocelot.UnitTests.Controllers
{ {
private OutputCacheController _controller; private OutputCacheController _controller;
private Mock<IOcelotCache<HttpResponseMessage>> _cache; private Mock<IOcelotCache<HttpResponseMessage>> _cache;
private Mock<IRegionsGetter> _getter;
private IActionResult _result; private IActionResult _result;
public OutputCacheControllerTests() public OutputCacheControllerTests()
{ {
_cache = new Mock<IOcelotCache<HttpResponseMessage>>(); _cache = new Mock<IOcelotCache<HttpResponseMessage>>();
_controller = new OutputCacheController(_cache.Object); _getter = new Mock<IRegionsGetter>();
_controller = new OutputCacheController(_cache.Object, _getter.Object);
} }
[Fact] [Fact]