massive refactor to handle creating load balancer first time a re route is called

This commit is contained in:
Tom Gardham-Pallister
2017-11-08 21:26:49 +00:00
parent ab14df9127
commit e43732290a
33 changed files with 294 additions and 319 deletions

View File

@ -3,11 +3,13 @@ using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
using Ocelot.ServiceDiscovery;
using TestStack.BDDfy;
@ -60,7 +62,7 @@ namespace Ocelot.AcceptanceTests
var consulConfig = new ConsulRegistryConfiguration("localhost", 9500, "Ocelot");
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl))
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", 200, "Hello from Laura"))
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", "", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig(consulConfig))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
@ -69,6 +71,69 @@ namespace Ocelot.AcceptanceTests
.BDDfy();
}
[Fact]
public void should_fix_issue_142()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
},
GlobalConfiguration = new FileGlobalConfiguration()
{
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
{
Provider = "Consul",
Host = "localhost",
Port = 9500
}
}
};
var fakeConsulServiceDiscoveryUrl = "http://localhost:9500";
var consulConfig = new ConsulRegistryConfiguration("localhost", 9500, "Ocelot");
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProvider("Consul")
.WithServiceDiscoveryProviderHost("localhost")
.WithServiceDiscoveryProviderPort(8500)
.Build();
var reRoute = new ReRouteBuilder()
.WithDownstreamPathTemplate("/status")
.WithUpstreamTemplatePattern("^(?i)/cs/status/$")
.WithDownstreamScheme("http")
.WithDownstreamHost("localhost")
.WithDownstreamPort(51779)
.WithUpstreamPathTemplate("/cs/status")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.WithLoadBalancer("LeastConnection")
.WithLoadBalancerKey("/cs/status|Get")
.WithServiceName("")
.WithUseServiceDiscovery(true)
.Build();
var reRoutes = new List<ReRoute> { reRoute };
var config = new OcelotConfiguration(reRoutes, null, serviceProviderConfig);
this.Given(x => GivenTheConsulConfigurationIs(config))
.And(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl))
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", "/status", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig(consulConfig))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/cs/status"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
private void GivenTheConsulConfigurationIs(OcelotConfiguration config)
{
_config = config;
}
private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url)
{
_fakeConsulBuilder = new WebHostBuilder()
@ -137,7 +202,7 @@ namespace Ocelot.AcceptanceTests
public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e";
}
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
private void GivenThereIsAServiceRunningOn(string url, string basePath, int statusCode, string responseBody)
{
_builder = new WebHostBuilder()
.UseUrls(url)
@ -147,6 +212,8 @@ namespace Ocelot.AcceptanceTests
.UseUrls(url)
.Configure(app =>
{
app.UsePathBase(basePath);
app.Run(async context =>
{
context.Response.StatusCode = statusCode;

View File

@ -44,7 +44,6 @@ namespace Ocelot.UnitTests.Configuration
private Mock<IRateLimitOptionsCreator> _rateLimitOptions;
private Mock<IRegionCreator> _regionCreator;
private Mock<IHttpHandlerOptionsCreator> _httpHandlerOptionsCreator;
private Mock<ILoadBalancerCreator> _lbCreator;
public FileConfigurationCreatorTests()
{
@ -65,11 +64,9 @@ namespace Ocelot.UnitTests.Configuration
_rateLimitOptions = new Mock<IRateLimitOptionsCreator>();
_regionCreator = new Mock<IRegionCreator>();
_httpHandlerOptionsCreator = new Mock<IHttpHandlerOptionsCreator>();
_lbCreator = new Mock<ILoadBalancerCreator>();
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
_fileConfig.Object, _validator.Object, _logger.Object,
_lbCreator.Object,
_qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object,
_authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object,
_serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object,
@ -189,32 +186,6 @@ namespace Ocelot.UnitTests.Configuration
.BDDfy();
}
[Fact]
public void should_create_load_balancer()
{
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" },
}
},
}))
.And(x => x.GivenTheConfigIsValid())
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
.When(x => x.WhenICreateTheConfig())
.And(x => x.ThenTheLoadBalancerCreatorIsCalledCorrectly())
.BDDfy();
}
[Fact]
public void should_use_downstream_host()
{
@ -320,12 +291,8 @@ namespace Ocelot.UnitTests.Configuration
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder()
.WithUseServiceDiscovery(true)
.WithServiceDiscoveryProvider("consul")
.WithServiceDiscoveryProviderHost("127.0.0.1")
.WithServiceName("ProductService")
.Build())
.WithUseServiceDiscovery(true)
.WithServiceName("ProductService")
.Build()
}))
.BDDfy();
@ -359,9 +326,7 @@ namespace Ocelot.UnitTests.Configuration
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder()
.WithUseServiceDiscovery(false)
.Build())
.WithUseServiceDiscovery(false)
.Build()
}))
.BDDfy();
@ -604,20 +569,6 @@ namespace Ocelot.UnitTests.Configuration
}
}
private void ThenTheServiceConfigurationIs(ServiceProviderConfiguration expected)
{
for (int i = 0; i < _config.Data.ReRoutes.Count; i++)
{
var result = _config.Data.ReRoutes[i];
result.ServiceProviderConfiguraion.DownstreamHost.ShouldBe(expected.DownstreamHost);
result.ServiceProviderConfiguraion.DownstreamPort.ShouldBe(expected.DownstreamPort);
result.ServiceProviderConfiguraion.ServiceDiscoveryProvider.ShouldBe(expected.ServiceDiscoveryProvider);
result.ServiceProviderConfiguraion.ServiceName.ShouldBe(expected.ServiceName);
result.ServiceProviderConfiguraion.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost);
result.ServiceProviderConfiguraion.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort);
}
}
private void ThenTheAuthenticationOptionsAre(List<ReRoute> expectedReRoutes)
{
for (int i = 0; i < _config.Data.ReRoutes.Count; i++)
@ -628,11 +579,6 @@ namespace Ocelot.UnitTests.Configuration
}
}
private void ThenTheLoadBalancerCreatorIsCalledCorrectly()
{
_lbCreator.Verify(x => x.SetupLoadBalancer(It.IsAny<ReRoute>()), Times.Once);
}
private void GivenTheQosProviderFactoryReturns()
{
_qosProviderFactory

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File;
using Ocelot.Configuration.Repository;
@ -36,7 +37,8 @@ namespace Ocelot.UnitTests.Configuration
public void should_set_configuration()
{
var fileConfig = new FileConfiguration();
var config = new OcelotConfiguration(new List<ReRoute>(), string.Empty);
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
var config = new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig);
this.Given(x => GivenTheFollowingConfiguration(fileConfig))
.And(x => GivenTheRepoReturns(new OkResponse()))

View File

@ -92,6 +92,8 @@ namespace Ocelot.UnitTests.Configuration
};
public string AdministrationPath {get;}
public ServiceProviderConfiguration ServiceProviderConfiguration => throw new NotImplementedException();
}
}
}

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.Provider;
using Ocelot.Configuration.Repository;
@ -27,9 +28,11 @@ namespace Ocelot.UnitTests.Configuration
[Fact]
public void should_get_config()
{
this.Given(x => x.GivenTheRepoReturns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty))))
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenTheRepoReturns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig))))
.When(x => x.WhenIGetTheConfig())
.Then(x => x.TheFollowingIsReturned(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty))))
.Then(x => x.TheFollowingIsReturned(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig))))
.BDDfy();
}

View File

@ -60,15 +60,12 @@ namespace Ocelot.UnitTests.Configuration
private void WhenICreate()
{
_result = _creator.Create(_reRoute, _globalConfig);
_result = _creator.Create(_globalConfig);
}
private void ThenTheConfigIs(ServiceProviderConfiguration expected)
{
_result.DownstreamHost.ShouldBe(expected.DownstreamHost);
_result.DownstreamPort.ShouldBe(expected.DownstreamPort);
_result.ServiceDiscoveryProvider.ShouldBe(expected.ServiceDiscoveryProvider);
_result.ServiceName.ShouldBe(expected.ServiceName);
_result.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost);
_result.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort);
}

View File

@ -36,6 +36,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact]
public void should_return_route()
{
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/"))
.And(x =>x.GivenTheTemplateVariableAndNameFinderReturns(
new OkResponse<List<UrlPathPlaceholderNameAndValue>>(
@ -48,7 +50,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath")
.Build()
}, string.Empty
}, string.Empty, serviceProviderConfig
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
@ -69,6 +71,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact]
public void should_append_slash_to_upstream_url_path()
{
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher"))
.And(x =>x.GivenTheTemplateVariableAndNameFinderReturns(
new OkResponse<List<UrlPathPlaceholderNameAndValue>>(
@ -81,7 +85,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath")
.Build()
}, string.Empty
}, string.Empty, serviceProviderConfig
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
@ -101,6 +105,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact]
public void should_return_route_if_upstream_path_and_upstream_template_are_the_same()
{
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And(
x =>
@ -114,7 +120,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath")
.Build()
}, string.Empty
}, string.Empty, serviceProviderConfig
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
@ -133,6 +139,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact]
public void should_return_correct_route_for_http_verb()
{
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And(
x =>
@ -152,7 +160,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern("")
.Build()
}, string.Empty
}, string.Empty, serviceProviderConfig
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
@ -169,7 +177,9 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact]
public void should_not_return_route()
{
{
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("dontMatchPath/"))
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
@ -179,7 +189,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("somePath")
.Build(),
}, string.Empty
}, string.Empty, serviceProviderConfig
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(false))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
@ -193,6 +203,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact]
public void should_return_correct_route_for_http_verb_setting_multiple_upstream_http_method()
{
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And(
x =>
@ -206,7 +218,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get", "Post" })
.WithUpstreamTemplatePattern("")
.Build()
}, string.Empty
}, string.Empty, serviceProviderConfig
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
@ -224,6 +236,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact]
public void should_return_correct_route_for_http_verb_setting_all_upstream_http_method()
{
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And(
x =>
@ -237,7 +251,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string>())
.WithUpstreamTemplatePattern("")
.Build()
}, string.Empty
}, string.Empty, serviceProviderConfig
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
@ -255,6 +269,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact]
public void should_not_return_route_for_http_verb_not_setting_in_upstream_http_method()
{
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And(
x =>
@ -268,7 +284,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" })
.WithUpstreamTemplatePattern("")
.Build()
}, string.Empty
}, string.Empty, serviceProviderConfig
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
@ -322,12 +338,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.Returns(_match);
}
private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath)
private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig)
{
_reRoutesConfig = reRoutesConfig;
_mockConfig
.Setup(x => x.Get())
.ReturnsAsync(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(_reRoutesConfig, adminPath)));
.ReturnsAsync(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig)));
}
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)

View File

@ -1,57 +0,0 @@
using Xunit;
using Shouldly;
using TestStack.BDDfy;
using Ocelot.LoadBalancer;
using Ocelot.LoadBalancer.LoadBalancers;
using Moq;
using Ocelot.Configuration;
using System.Collections.Generic;
using Ocelot.Values;
using Ocelot.Configuration.Builder;
namespace Ocelot.UnitTests.LoadBalancer
{
public class LoadBalancerCreatorTests
{
private LoadBalancerCreator _creator;
private ILoadBalancerHouse _house;
private Mock<ILoadBalancerFactory> _factory;
private ReRoute _reRoute;
public LoadBalancerCreatorTests()
{
_house = new LoadBalancerHouse();
_factory = new Mock<ILoadBalancerFactory>();
_creator = new LoadBalancerCreator(_house, _factory.Object);
}
[Fact]
public void should_create_load_balancer()
{
var reRoute = new ReRouteBuilder().WithLoadBalancerKey("Test").Build();
this.Given(x => GivenTheFollowingReRoute(reRoute))
.When(x => WhenICallTheCreator())
.Then(x => x.ThenTheLoadBalancerIsCreated())
.BDDfy();
}
private void GivenTheFollowingReRoute(ReRoute reRoute)
{
_reRoute = reRoute;
_factory
.Setup(x => x.Get(It.IsAny<ReRoute>()))
.ReturnsAsync(new NoLoadBalancer(new List<Service>()));
}
private void WhenICallTheCreator()
{
_creator.SetupLoadBalancer(_reRoute).Wait();
}
private void ThenTheLoadBalancerIsCreated()
{
var lb = _house.Get(_reRoute.ReRouteKey);
lb.ShouldNotBeNull();
}
}
}

View File

@ -17,7 +17,8 @@ namespace Ocelot.UnitTests.LoadBalancer
private ILoadBalancer _result;
private Mock<IServiceDiscoveryProviderFactory> _serviceProviderFactory;
private Mock<IServiceDiscoveryProvider> _serviceProvider;
private ServiceProviderConfiguration _serviceProviderConfig;
public LoadBalancerFactoryTests()
{
_serviceProviderFactory = new Mock<IServiceDiscoveryProviderFactory>();
@ -29,11 +30,11 @@ namespace Ocelot.UnitTests.LoadBalancer
public void should_return_no_load_balancer()
{
var reRoute = new ReRouteBuilder()
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build();
this.Given(x => x.GivenAReRoute(reRoute))
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
.And(x => x.GivenTheServiceProviderFactoryReturns())
.When(x => x.WhenIGetTheLoadBalancer())
.Then(x => x.ThenTheLoadBalancerIsReturned<NoLoadBalancer>())
@ -46,10 +47,10 @@ namespace Ocelot.UnitTests.LoadBalancer
var reRoute = new ReRouteBuilder()
.WithLoadBalancer("RoundRobin")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.Build();
this.Given(x => x.GivenAReRoute(reRoute))
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
.And(x => x.GivenTheServiceProviderFactoryReturns())
.When(x => x.WhenIGetTheLoadBalancer())
.Then(x => x.ThenTheLoadBalancerIsReturned<RoundRobinLoadBalancer>())
@ -62,10 +63,10 @@ namespace Ocelot.UnitTests.LoadBalancer
var reRoute = new ReRouteBuilder()
.WithLoadBalancer("LeastConnection")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.Build();
this.Given(x => x.GivenAReRoute(reRoute))
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
.And(x => x.GivenTheServiceProviderFactoryReturns())
.When(x => x.WhenIGetTheLoadBalancer())
.Then(x => x.ThenTheLoadBalancerIsReturned<LeastConnectionLoadBalancer>())
@ -78,27 +79,32 @@ namespace Ocelot.UnitTests.LoadBalancer
var reRoute = new ReRouteBuilder()
.WithLoadBalancer("RoundRobin")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.Build();
this.Given(x => x.GivenAReRoute(reRoute))
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
.And(x => x.GivenTheServiceProviderFactoryReturns())
.When(x => x.WhenIGetTheLoadBalancer())
.Then(x => x.ThenTheServiceProviderIsCalledCorrectly())
.BDDfy();
}
private void GivenAServiceProviderConfig(ServiceProviderConfiguration serviceProviderConfig)
{
_serviceProviderConfig = serviceProviderConfig;
}
private void GivenTheServiceProviderFactoryReturns()
{
_serviceProviderFactory
.Setup(x => x.Get(It.IsAny<ServiceProviderConfiguration>()))
.Setup(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()))
.Returns(_serviceProvider.Object);
}
private void ThenTheServiceProviderIsCalledCorrectly()
{
_serviceProviderFactory
.Verify(x => x.Get(It.IsAny<ServiceProviderConfiguration>()), Times.Once);
.Verify(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()), Times.Once);
}
private void GivenAReRoute(ReRoute reRoute)
@ -108,7 +114,7 @@ namespace Ocelot.UnitTests.LoadBalancer
private void WhenIGetTheLoadBalancer()
{
_result = _factory.Get(_reRoute).Result;
_result = _factory.Get(_reRoute, _serviceProviderConfig).Result;
}
private void ThenTheLoadBalancerIsReturned<T>()

View File

@ -1,5 +1,8 @@
using System;
using System.Threading.Tasks;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.LoadBalancer.LoadBalancers;
using Ocelot.Responses;
using Ocelot.Values;
@ -11,35 +14,38 @@ namespace Ocelot.UnitTests.LoadBalancer
{
public class LoadBalancerHouseTests
{
private ReRoute _reRoute;
private ILoadBalancer _loadBalancer;
private readonly LoadBalancerHouse _loadBalancerHouse;
private Response _addResult;
private Response<ILoadBalancer> _getResult;
private string _key;
private Mock<ILoadBalancerFactory> _factory;
private ServiceProviderConfiguration _serviceProviderConfig;
public LoadBalancerHouseTests()
{
_loadBalancerHouse = new LoadBalancerHouse();
_factory = new Mock<ILoadBalancerFactory>();
_loadBalancerHouse = new LoadBalancerHouse(_factory.Object);
}
[Fact]
public void should_store_load_balancer()
public void should_store_load_balancer_on_first_request()
{
var key = "test";
var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build();
this.Given(x => x.GivenThereIsALoadBalancer(key, new FakeLoadBalancer()))
.When(x => x.WhenIAddTheLoadBalancer())
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.Then(x => x.ThenItIsAdded())
.BDDfy();
}
[Fact]
public void should_get_load_balancer()
public void should_not_store_load_balancer_on_second_request()
{
var key = "test";
var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build();
this.Given(x => x.GivenThereIsALoadBalancer(key, new FakeLoadBalancer()))
.When(x => x.WhenWeGetTheLoadBalancer(key))
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
.Then(x => x.ThenItIsReturned())
.BDDfy();
}
@ -47,26 +53,50 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_store_load_balancers_by_key()
{
var key = "test";
var keyTwo = "testTwo";
var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build();
var reRouteTwo = new ReRouteBuilder().WithLoadBalancerKey("testtwo").Build();
this.Given(x => x.GivenThereIsALoadBalancer(key, new FakeLoadBalancer()))
.And(x => x.GivenThereIsALoadBalancer(keyTwo, new FakeRoundRobinLoadBalancer()))
.When(x => x.WhenWeGetTheLoadBalancer(key))
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.And(x => x.GivenThereIsALoadBalancer(reRouteTwo, new FakeRoundRobinLoadBalancer()))
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
.Then(x => x.ThenTheLoadBalancerIs<FakeLoadBalancer>())
.When(x => x.WhenWeGetTheLoadBalancer(keyTwo))
.When(x => x.WhenWeGetTheLoadBalancer(reRouteTwo))
.Then(x => x.ThenTheLoadBalancerIs<FakeRoundRobinLoadBalancer>())
.BDDfy();
}
[Fact]
public void should_return_error_if_no_load_balancer_with_key()
public void should_return_error_if_exception()
{
this.When(x => x.WhenWeGetTheLoadBalancer("test"))
var reRoute = new ReRouteBuilder().Build();
this.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
.Then(x => x.ThenAnErrorIsReturned())
.BDDfy();
}
[Fact]
public void should_get_new_load_balancer_if_reroute_load_balancer_has_changed()
{
var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build();
var reRouteTwo = new ReRouteBuilder().WithLoadBalancer("LeastConnection").WithLoadBalancerKey("test").Build();
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
.Then(x => x.ThenTheLoadBalancerIs<FakeLoadBalancer>())
.When(x => x.WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(reRouteTwo))
.Then(x => x.ThenTheLoadBalancerIs<LeastConnectionLoadBalancer>())
.BDDfy();
}
private void WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(ReRoute reRoute)
{
_reRoute = reRoute;
_factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(new LeastConnectionLoadBalancer(null, null));
_getResult = _loadBalancerHouse.Get(_reRoute, _serviceProviderConfig).Result;
}
private void ThenAnErrorIsReturned()
{
_getResult.IsError.ShouldBeTrue();
@ -80,31 +110,30 @@ namespace Ocelot.UnitTests.LoadBalancer
private void ThenItIsAdded()
{
_addResult.IsError.ShouldBe(false);
_addResult.ShouldBeOfType<OkResponse>();
}
private void WhenIAddTheLoadBalancer()
{
_addResult = _loadBalancerHouse.Add(_key, _loadBalancer);
_getResult.IsError.ShouldBe(false);
_getResult.ShouldBeOfType<OkResponse<ILoadBalancer>>();
_getResult.Data.ShouldBe(_loadBalancer);
_factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once);
}
private void GivenThereIsALoadBalancer(string key, ILoadBalancer loadBalancer)
private void GivenThereIsALoadBalancer(ReRoute reRoute, ILoadBalancer loadBalancer)
{
_key = key;
_reRoute = reRoute;
_loadBalancer = loadBalancer;
WhenIAddTheLoadBalancer();
_factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(loadBalancer);
_getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result;
}
private void WhenWeGetTheLoadBalancer(string key)
private void WhenWeGetTheLoadBalancer(ReRoute reRoute)
{
_getResult = _loadBalancerHouse.Get(key);
_getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result;
}
private void ThenItIsReturned()
{
_getResult.Data.ShouldBe(_loadBalancer);
_factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once);
}
class FakeLoadBalancer : ILoadBalancer

View File

@ -5,6 +5,7 @@ namespace Ocelot.UnitTests.LoadBalancer
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder;
using Ocelot.Errors;
@ -137,8 +138,8 @@ namespace Ocelot.UnitTests.LoadBalancer
private void GivenTheLoadBalancerHouseReturns()
{
_loadBalancerHouse
.Setup(x => x.Get(It.IsAny<string>()))
.Returns(new OkResponse<ILoadBalancer>(_loadBalancer.Object));
.Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
.ReturnsAsync(new OkResponse<ILoadBalancer>(_loadBalancer.Object));
}
private void GivenTheLoadBalancerHouseReturnsAnError()
@ -149,8 +150,8 @@ namespace Ocelot.UnitTests.LoadBalancer
});
_loadBalancerHouse
.Setup(x => x.Get(It.IsAny<string>()))
.Returns(_getLoadBalancerHouseError);
.Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
.ReturnsAsync(_getLoadBalancerHouseError);
}
private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline()

View File

@ -12,6 +12,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
private ServiceProviderConfiguration _serviceConfig;
private IServiceDiscoveryProvider _result;
private readonly ServiceDiscoveryProviderFactory _factory;
private ReRoute _reRoute;
public ServiceProviderFactoryTests()
{
@ -22,12 +23,11 @@ namespace Ocelot.UnitTests.ServiceDiscovery
public void should_return_no_service_provider()
{
var serviceConfig = new ServiceProviderConfigurationBuilder()
.WithDownstreamHost("127.0.0.1")
.WithDownstreamPort(80)
.WithUseServiceDiscovery(false)
.Build();
this.Given(x => x.GivenTheReRoute(serviceConfig))
var reRoute = new ReRouteBuilder().Build();
this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))
.When(x => x.WhenIGetTheServiceProvider())
.Then(x => x.ThenTheServiceProviderIs<ConfigurationServiceProvider>())
.BDDfy();
@ -36,26 +36,30 @@ namespace Ocelot.UnitTests.ServiceDiscovery
[Fact]
public void should_return_consul_service_provider()
{
var serviceConfig = new ServiceProviderConfigurationBuilder()
var reRoute = new ReRouteBuilder()
.WithServiceName("product")
.WithUseServiceDiscovery(true)
.Build();
var serviceConfig = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProvider("Consul")
.Build();
this.Given(x => x.GivenTheReRoute(serviceConfig))
this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))
.When(x => x.WhenIGetTheServiceProvider())
.Then(x => x.ThenTheServiceProviderIs<ConsulServiceDiscoveryProvider>())
.BDDfy();
}
private void GivenTheReRoute(ServiceProviderConfiguration serviceConfig)
private void GivenTheReRoute(ServiceProviderConfiguration serviceConfig, ReRoute reRoute)
{
_serviceConfig = serviceConfig;
_reRoute = reRoute;
}
private void WhenIGetTheServiceProvider()
{
_result = _factory.Get(_serviceConfig);
_result = _factory.Get(_serviceConfig, _reRoute);
}
private void ThenTheServiceProviderIs<T>()