mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 16:28:17 +08:00
Rewire LoadBalancerFactory to allow injecting custom load balancers, by introducing LoadBalancerCreators
This commit is contained in:
@ -0,0 +1,73 @@
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class CookieStickySessionsCreatorTests
|
||||
{
|
||||
private readonly CookieStickySessionsCreator _creator;
|
||||
private readonly Mock<IServiceDiscoveryProvider> _serviceProvider;
|
||||
private DownstreamReRoute _reRoute;
|
||||
private ILoadBalancer _loadBalancer;
|
||||
private string _typeName;
|
||||
|
||||
public CookieStickySessionsCreatorTests()
|
||||
{
|
||||
_creator = new CookieStickySessionsCreator();
|
||||
_serviceProvider = new Mock<IServiceDiscoveryProvider>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_expected_name()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("myType", "myKey", 1000))
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<CookieStickySessions>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_instance_of_expected_load_balancer_type()
|
||||
{
|
||||
this.When(x => x.WhenIGetTheLoadBalancerTypeName())
|
||||
.Then(x => x.ThenTheLoadBalancerTypeIs("CookieStickySessions"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenAReRoute(DownstreamReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancer()
|
||||
{
|
||||
_loadBalancer = _creator.Create(_reRoute, _serviceProvider.Object);
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancerTypeName()
|
||||
{
|
||||
_typeName = _creator.Type;
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerIsReturned<T>()
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
_loadBalancer.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerTypeIs(string type)
|
||||
{
|
||||
_typeName.ShouldBe(type);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class LeastConnectionCreatorTests
|
||||
{
|
||||
private readonly LeastConnectionCreator _creator;
|
||||
private readonly Mock<IServiceDiscoveryProvider> _serviceProvider;
|
||||
private DownstreamReRoute _reRoute;
|
||||
private ILoadBalancer _loadBalancer;
|
||||
private string _typeName;
|
||||
|
||||
public LeastConnectionCreatorTests()
|
||||
{
|
||||
_creator = new LeastConnectionCreator();
|
||||
_serviceProvider = new Mock<IServiceDiscoveryProvider>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_expected_name()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithServiceName("myService")
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<LeastConnection>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_instance_of_expected_load_balancer_type()
|
||||
{
|
||||
this.When(x => x.WhenIGetTheLoadBalancerTypeName())
|
||||
.Then(x => x.ThenTheLoadBalancerTypeIs("LeastConnection"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenAReRoute(DownstreamReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancer()
|
||||
{
|
||||
_loadBalancer = _creator.Create(_reRoute, _serviceProvider.Object);
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancerTypeName()
|
||||
{
|
||||
_typeName = _creator.Type;
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerIsReturned<T>()
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
_loadBalancer.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerTypeIs(string type)
|
||||
{
|
||||
_typeName.ShouldBe(type);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,9 @@ using Ocelot.ServiceDiscovery;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Values;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
@ -18,6 +21,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
private readonly LoadBalancerFactory _factory;
|
||||
private Response<ILoadBalancer> _result;
|
||||
private readonly Mock<IServiceDiscoveryProviderFactory> _serviceProviderFactory;
|
||||
private readonly IEnumerable<ILoadBalancerCreator> _loadBalancerCreators;
|
||||
private readonly Mock<IServiceDiscoveryProvider> _serviceProvider;
|
||||
private ServiceProviderConfiguration _serviceProviderConfig;
|
||||
|
||||
@ -25,7 +29,13 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
_serviceProviderFactory = new Mock<IServiceDiscoveryProviderFactory>();
|
||||
_serviceProvider = new Mock<IServiceDiscoveryProvider>();
|
||||
_factory = new LoadBalancerFactory(_serviceProviderFactory.Object);
|
||||
_loadBalancerCreators = new ILoadBalancerCreator[]
|
||||
{
|
||||
new FakeLoadBalancerCreator<FakeLoadBalancerOne>(),
|
||||
new FakeLoadBalancerCreator<FakeLoadBalancerTwo>(),
|
||||
new FakeLoadBalancerCreator<FakeNoLoadBalancer>(nameof(NoLoadBalancer)),
|
||||
};
|
||||
_factory = new LoadBalancerFactory(_serviceProviderFactory.Object, _loadBalancerCreators);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -39,15 +49,15 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<NoLoadBalancer>())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<FakeNoLoadBalancer>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_round_robin_load_balancer()
|
||||
public void should_return_matching_load_balancer()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("RoundRobin", "", 0))
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancerTwo", "", 0))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
@ -55,31 +65,15 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
|
||||
.And(x => x.GivenTheServiceProviderFactoryReturns())
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<RoundRobin>())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<FakeLoadBalancerTwo>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_round_least_connection_balancer()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("LeastConnection", "", 0))
|
||||
.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<LeastConnection>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void should_call_service_provider()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("RoundRobin", "", 0))
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("FakeLoadBalancerOne", "", 0))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
@ -91,22 +85,6 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_sticky_session()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithLoadBalancerOptions(new LoadBalancerOptions("CookieStickySessions", "", 0))
|
||||
.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<CookieStickySessions>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenAServiceProviderConfig(ServiceProviderConfiguration serviceProviderConfig)
|
||||
{
|
||||
_serviceProviderConfig = serviceProviderConfig;
|
||||
@ -139,5 +117,66 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
_result.Data.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private class FakeLoadBalancerCreator<T> : ILoadBalancerCreator
|
||||
where T : ILoadBalancer, new()
|
||||
{
|
||||
|
||||
public FakeLoadBalancerCreator()
|
||||
{
|
||||
Type = typeof(T).Name;
|
||||
}
|
||||
|
||||
public FakeLoadBalancerCreator(string type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public ILoadBalancer Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
|
||||
public string Type { get; }
|
||||
}
|
||||
|
||||
private class FakeLoadBalancerOne : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void Release(ServiceHostAndPort hostAndPort)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class FakeLoadBalancerTwo : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void Release(ServiceHostAndPort hostAndPort)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class FakeNoLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void Release(ServiceHostAndPort hostAndPort)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class NoLoadBalancerCreatorTests
|
||||
{
|
||||
private readonly NoLoadBalancerCreator _creator;
|
||||
private readonly Mock<IServiceDiscoveryProvider> _serviceProvider;
|
||||
private DownstreamReRoute _reRoute;
|
||||
private ILoadBalancer _loadBalancer;
|
||||
private string _typeName;
|
||||
|
||||
public NoLoadBalancerCreatorTests()
|
||||
{
|
||||
_creator = new NoLoadBalancerCreator();
|
||||
_serviceProvider = new Mock<IServiceDiscoveryProvider>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_expected_name()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<NoLoadBalancer>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_instance_of_expected_load_balancer_type()
|
||||
{
|
||||
this.When(x => x.WhenIGetTheLoadBalancerTypeName())
|
||||
.Then(x => x.ThenTheLoadBalancerTypeIs("NoLoadBalancer"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenAReRoute(DownstreamReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancer()
|
||||
{
|
||||
_loadBalancer = _creator.Create(_reRoute, _serviceProvider.Object);
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancerTypeName()
|
||||
{
|
||||
_typeName = _creator.Type;
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerIsReturned<T>()
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
_loadBalancer.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerTypeIs(string type)
|
||||
{
|
||||
_typeName.ShouldBe(type);
|
||||
}
|
||||
}
|
||||
}
|
72
test/Ocelot.UnitTests/LoadBalancer/RoundRobinCreatorTests.cs
Normal file
72
test/Ocelot.UnitTests/LoadBalancer/RoundRobinCreatorTests.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
public class RoundRobinCreatorTests
|
||||
{
|
||||
private readonly RoundRobinCreator _creator;
|
||||
private readonly Mock<IServiceDiscoveryProvider> _serviceProvider;
|
||||
private DownstreamReRoute _reRoute;
|
||||
private ILoadBalancer _loadBalancer;
|
||||
private string _typeName;
|
||||
|
||||
public RoundRobinCreatorTests()
|
||||
{
|
||||
_creator = new RoundRobinCreator();
|
||||
_serviceProvider = new Mock<IServiceDiscoveryProvider>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_expected_name()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenAReRoute(reRoute))
|
||||
.When(x => x.WhenIGetTheLoadBalancer())
|
||||
.Then(x => x.ThenTheLoadBalancerIsReturned<RoundRobin>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_instance_of_expected_load_balancer_type()
|
||||
{
|
||||
this.When(x => x.WhenIGetTheLoadBalancerTypeName())
|
||||
.Then(x => x.ThenTheLoadBalancerTypeIs("RoundRobin"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenAReRoute(DownstreamReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancer()
|
||||
{
|
||||
_loadBalancer = _creator.Create(_reRoute, _serviceProvider.Object);
|
||||
}
|
||||
|
||||
private void WhenIGetTheLoadBalancerTypeName()
|
||||
{
|
||||
_typeName = _creator.Type;
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerIsReturned<T>()
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
_loadBalancer.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void ThenTheLoadBalancerTypeIs(string type)
|
||||
{
|
||||
_typeName.ShouldBe(type);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user