mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 10:35:28 +08:00 
			
		
		
		
	Feature/inject error mapper (#562)
* added delegate to select last handler * #529 implemented a way we can inject the last delegating handler * wip - moving code * #529 removed loads of qos code and moved it into Ocelot.Provider.Polly * #529 can now inject http client expcetions to ocelot errors mappers and updated docs
This commit is contained in:
		@@ -5,7 +5,22 @@ Ocelot supports one QoS capability at the current time. You can set on a per ReR
 | 
			
		||||
want to use a circuit breaker when making requests to a downstream service. This uses the an awesome
 | 
			
		||||
.NET library called Polly check them out `here <https://github.com/App-vNext/Polly>`_.
 | 
			
		||||
 | 
			
		||||
Add the following section to a ReRoute configuration. 
 | 
			
		||||
The first thing you need to do if you want to use the administration API is bring in the relavent NuGet package..
 | 
			
		||||
 | 
			
		||||
``Install-Package Ocelot.Provider.Polly``
 | 
			
		||||
 | 
			
		||||
Then in your ConfigureServices method
 | 
			
		||||
 | 
			
		||||
.. code-block:: csharp
 | 
			
		||||
 | 
			
		||||
    public virtual void ConfigureServices(IServiceCollection services)
 | 
			
		||||
    {
 | 
			
		||||
        services
 | 
			
		||||
            .AddOcelot()
 | 
			
		||||
            .AddPolly();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
Then add the following section to a ReRoute configuration. 
 | 
			
		||||
 | 
			
		||||
.. code-block:: json
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,6 @@
 | 
			
		||||
            int durationofBreak, 
 | 
			
		||||
            int timeoutValue, 
 | 
			
		||||
            string key,
 | 
			
		||||
            //todo - this is never set in Ocelot so always Pessimistic...I guess it doesn't
 | 
			
		||||
            //matter to much.
 | 
			
		||||
            string timeoutStrategy = "Pessimistic")
 | 
			
		||||
        {
 | 
			
		||||
            ExceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
 | 
			
		||||
 
 | 
			
		||||
@@ -130,6 +130,7 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            Services.TryAddSingleton<IDownstreamRequestCreator, DownstreamRequestCreator>();
 | 
			
		||||
            Services.TryAddSingleton<IFrameworkDescription, FrameworkDescription>();
 | 
			
		||||
            Services.TryAddSingleton<IQoSFactory, QoSFactory>();
 | 
			
		||||
            Services.TryAddSingleton<IExceptionToErrorMapper, HttpExeptionToErrorMapper>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IOcelotBuilder AddSingletonDefinedAggregator<T>() 
 | 
			
		||||
 
 | 
			
		||||
@@ -12,14 +12,17 @@ namespace Ocelot.Requester
 | 
			
		||||
        private readonly IHttpClientCache _cacheHandlers;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IDelegatingHandlerHandlerFactory _factory;
 | 
			
		||||
        private readonly IExceptionToErrorMapper _mapper;
 | 
			
		||||
 | 
			
		||||
        public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IHttpClientCache cacheHandlers,
 | 
			
		||||
            IDelegatingHandlerHandlerFactory house)
 | 
			
		||||
            IDelegatingHandlerHandlerFactory factory, 
 | 
			
		||||
            IExceptionToErrorMapper mapper)
 | 
			
		||||
        {
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<HttpClientHttpRequester>();
 | 
			
		||||
            _cacheHandlers = cacheHandlers;
 | 
			
		||||
            _factory = house;
 | 
			
		||||
            _factory = factory;
 | 
			
		||||
            _mapper = mapper;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext context)
 | 
			
		||||
@@ -35,7 +38,8 @@ namespace Ocelot.Requester
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception exception)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<HttpResponseMessage>(new UnableToCompleteRequestError(exception));
 | 
			
		||||
                var error = _mapper.Map(exception);
 | 
			
		||||
                return new ErrorResponse<HttpResponseMessage>(error);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								src/Ocelot/Requester/HttpExeptionToErrorMapper.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/Ocelot/Requester/HttpExeptionToErrorMapper.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using Errors;
 | 
			
		||||
    using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
    public class HttpExeptionToErrorMapper : IExceptionToErrorMapper
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Dictionary<Type, Func<Exception, Error>> _mappers;
 | 
			
		||||
 | 
			
		||||
        public HttpExeptionToErrorMapper(IServiceProvider serviceProvider)
 | 
			
		||||
        {
 | 
			
		||||
            _mappers = serviceProvider.GetService<Dictionary<Type, Func<Exception, Error>>>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Error Map(Exception exception)
 | 
			
		||||
        {
 | 
			
		||||
            var type = exception.GetType();
 | 
			
		||||
 | 
			
		||||
            if (_mappers != null && _mappers.ContainsKey(type))
 | 
			
		||||
            {
 | 
			
		||||
                return _mappers[type](exception);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new UnableToCompleteRequestError(exception);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/Ocelot/Requester/IExceptionToErrorMapper.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/Ocelot/Requester/IExceptionToErrorMapper.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
using System;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public interface IExceptionToErrorMapper
 | 
			
		||||
    {
 | 
			
		||||
        Error Map(Exception exception);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class ReRouteDelegatingHandler<T> 
 | 
			
		||||
        where T : DelegatingHandler
 | 
			
		||||
    {
 | 
			
		||||
        public T DelegatingHandler { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class UnableToFindDelegatingHandlerProviderError : Error
 | 
			
		||||
    {
 | 
			
		||||
        public UnableToFindDelegatingHandlerProviderError(string message)
 | 
			
		||||
            : base(message, OcelotErrorCode.UnableToFindDelegatingHandlerProviderError)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -27,6 +27,7 @@ namespace Ocelot.UnitTests.Requester
 | 
			
		||||
        private DownstreamContext _request;
 | 
			
		||||
        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
			
		||||
        private Mock<IOcelotLogger> _logger;
 | 
			
		||||
        private Mock<IExceptionToErrorMapper> _mapper;
 | 
			
		||||
 | 
			
		||||
        public HttpClientHttpRequesterTest()
 | 
			
		||||
        {
 | 
			
		||||
@@ -38,10 +39,12 @@ namespace Ocelot.UnitTests.Requester
 | 
			
		||||
                .Setup(x => x.CreateLogger<HttpClientHttpRequester>())
 | 
			
		||||
                .Returns(_logger.Object);
 | 
			
		||||
            _cacheHandlers = new Mock<IHttpClientCache>();
 | 
			
		||||
            _mapper = new Mock<IExceptionToErrorMapper>();
 | 
			
		||||
            _httpClientRequester = new HttpClientHttpRequester(
 | 
			
		||||
                _loggerFactory.Object, 
 | 
			
		||||
                _cacheHandlers.Object, 
 | 
			
		||||
                _factory.Object);            
 | 
			
		||||
                _factory.Object,
 | 
			
		||||
                _mapper.Object);            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
@@ -144,6 +147,7 @@ namespace Ocelot.UnitTests.Requester
 | 
			
		||||
 | 
			
		||||
        private void ThenTheErrorIsTimeout()
 | 
			
		||||
        {
 | 
			
		||||
            _mapper.Verify(x => x.Map(It.IsAny<Exception>()), Times.Once);
 | 
			
		||||
            _response.Errors[0].ShouldBeOfType<UnableToCompleteRequestError>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -165,6 +169,8 @@ namespace Ocelot.UnitTests.Requester
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
 | 
			
		||||
 | 
			
		||||
            _mapper.Setup(x => x.Map(It.IsAny<Exception>())).Returns(new UnableToCompleteRequestError(new Exception()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class OkDelegatingHandler : DelegatingHandler
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,52 @@
 | 
			
		||||
namespace Ocelot.UnitTests.Requester
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.Threading.Tasks;
 | 
			
		||||
    using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
    using Ocelot.Errors;
 | 
			
		||||
    using Ocelot.Requester;
 | 
			
		||||
    using Responder;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
 | 
			
		||||
    public class HttpExeptionToErrorMapperTests
 | 
			
		||||
    {
 | 
			
		||||
        private HttpExeptionToErrorMapper _mapper;
 | 
			
		||||
        private readonly ServiceCollection _services;
 | 
			
		||||
 | 
			
		||||
        public HttpExeptionToErrorMapperTests()
 | 
			
		||||
        {
 | 
			
		||||
            _services = new ServiceCollection();
 | 
			
		||||
            var provider = _services.BuildServiceProvider();
 | 
			
		||||
            _mapper = new HttpExeptionToErrorMapper(provider);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_default_error_because_mappers_are_null()
 | 
			
		||||
        {
 | 
			
		||||
            var error = _mapper.Map(new Exception());
 | 
			
		||||
 | 
			
		||||
            error.ShouldBeOfType<UnableToCompleteRequestError>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_error_from_mapper()
 | 
			
		||||
        {
 | 
			
		||||
            var errorMapping = new Dictionary<Type, Func<Exception, Error>>
 | 
			
		||||
            {
 | 
			
		||||
                {typeof(TaskCanceledException), e => new AnyError()},
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _services.AddSingleton(errorMapping);
 | 
			
		||||
 | 
			
		||||
            var provider = _services.BuildServiceProvider();
 | 
			
		||||
 | 
			
		||||
            _mapper = new HttpExeptionToErrorMapper(provider);
 | 
			
		||||
 | 
			
		||||
            var error = _mapper.Map(new TaskCanceledException());
 | 
			
		||||
 | 
			
		||||
            error.ShouldBeOfType<AnyError>();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								test/Ocelot.UnitTests/Requester/QoSFactoryTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								test/Ocelot.UnitTests/Requester/QoSFactoryTests.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
namespace Ocelot.UnitTests.Requester
 | 
			
		||||
{
 | 
			
		||||
    using System.Net.Http;
 | 
			
		||||
    using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Configuration;
 | 
			
		||||
    using Ocelot.Configuration.Builder;
 | 
			
		||||
    using Ocelot.Logging;
 | 
			
		||||
    using Ocelot.Requester;
 | 
			
		||||
    using Ocelot.Requester.QoS;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
 | 
			
		||||
    public class QoSFactoryTests
 | 
			
		||||
    {
 | 
			
		||||
        private QoSFactory _factory;
 | 
			
		||||
        private ServiceCollection _services;
 | 
			
		||||
        private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
			
		||||
 | 
			
		||||
        public QoSFactoryTests()
 | 
			
		||||
        {
 | 
			
		||||
            _services = new ServiceCollection();
 | 
			
		||||
            _loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
            var provider = _services.BuildServiceProvider();
 | 
			
		||||
            _factory = new QoSFactory(provider, _loggerFactory.Object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_error()
 | 
			
		||||
        {
 | 
			
		||||
            var downstreamReRoute = new DownstreamReRouteBuilder().Build();
 | 
			
		||||
            var handler = _factory.Get(downstreamReRoute);
 | 
			
		||||
            handler.IsError.ShouldBeTrue();
 | 
			
		||||
            handler.Errors[0].ShouldBeOfType<UnableToFindQoSProviderError>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_handler()
 | 
			
		||||
        {
 | 
			
		||||
            _services = new ServiceCollection();
 | 
			
		||||
            DelegatingHandler QosDelegatingHandlerDelegate(DownstreamReRoute a, IOcelotLoggerFactory b) => new FakeDelegatingHandler();
 | 
			
		||||
            _services.AddSingleton<QosDelegatingHandlerDelegate>(QosDelegatingHandlerDelegate);
 | 
			
		||||
            var provider = _services.BuildServiceProvider();
 | 
			
		||||
            _factory = new QoSFactory(provider, _loggerFactory.Object);
 | 
			
		||||
            var downstreamReRoute = new DownstreamReRouteBuilder().Build();
 | 
			
		||||
            var handler = _factory.Get(downstreamReRoute);
 | 
			
		||||
            handler.IsError.ShouldBeFalse();
 | 
			
		||||
            handler.Data.ShouldBeOfType<FakeDelegatingHandler>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class FakeDelegatingHandler : DelegatingHandler
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,93 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
namespace Ocelot.UnitTests.Requester
 | 
			
		||||
{
 | 
			
		||||
    using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
    using Moq;
 | 
			
		||||
    using Ocelot.Configuration;
 | 
			
		||||
    using Ocelot.Configuration.Builder;
 | 
			
		||||
    using Ocelot.Logging;
 | 
			
		||||
    using Ocelot.Requester.QoS;
 | 
			
		||||
    using Shouldly;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using TestStack.BDDfy;
 | 
			
		||||
    using Xunit;
 | 
			
		||||
 | 
			
		||||
    public class QoSProviderFactoryTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IQoSProviderFactory _factory;
 | 
			
		||||
        private DownstreamReRoute _reRoute;
 | 
			
		||||
        private IQoSProvider _result;
 | 
			
		||||
        private Mock<IOcelotLoggerFactory> _loggerFactory;
 | 
			
		||||
        private Mock<IOcelotLogger> _logger;
 | 
			
		||||
 | 
			
		||||
        public QoSProviderFactoryTests()
 | 
			
		||||
        {
 | 
			
		||||
            _logger = new Mock<IOcelotLogger>();
 | 
			
		||||
            _loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
            var services = new ServiceCollection();
 | 
			
		||||
            var provider = services.BuildServiceProvider();
 | 
			
		||||
            _factory = new QoSProviderFactory(_loggerFactory.Object, provider);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_no_qos_provider()
 | 
			
		||||
        {
 | 
			
		||||
            var qosOptions = new QoSOptionsBuilder()
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var reRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithQosOptions(qosOptions)
 | 
			
		||||
                .WithUpstreamHttpMethod(new List<string> { "get" })
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenAReRoute(reRoute))
 | 
			
		||||
                .When(x => x.WhenIGetTheQoSProvider())
 | 
			
		||||
                .Then(x => x.ThenTheQoSProviderIsReturned<NoQoSProvider>())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_delegate_provider()
 | 
			
		||||
        {
 | 
			
		||||
            var qosOptions = new QoSOptionsBuilder()
 | 
			
		||||
                .WithTimeoutValue(100)
 | 
			
		||||
                .WithDurationOfBreak(100)
 | 
			
		||||
                .WithExceptionsAllowedBeforeBreaking(100)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var reRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithUpstreamHttpMethod(new List<string> { "get" })
 | 
			
		||||
                .WithQosOptions(qosOptions)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenAReRoute(reRoute))
 | 
			
		||||
                .When(x => x.WhenIGetTheQoSProvider())
 | 
			
		||||
                .Then(x => x.ThenTheQoSProviderIsReturned<FakeProvider>())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenAReRoute(DownstreamReRoute reRoute)
 | 
			
		||||
        {
 | 
			
		||||
            _reRoute = reRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIGetTheQoSProvider()
 | 
			
		||||
        {
 | 
			
		||||
            _result = _factory.Get(_reRoute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheQoSProviderIsReturned<T>()
 | 
			
		||||
        {
 | 
			
		||||
            _result.ShouldBeOfType<T>();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal class FakeProvider : IQoSProvider
 | 
			
		||||
    {
 | 
			
		||||
        public T CircuitBreaker<T>()
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
@@ -1,195 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using Ocelot.Requester.QoS;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Requester
 | 
			
		||||
{
 | 
			
		||||
    public class QosProviderHouseTests
 | 
			
		||||
    {
 | 
			
		||||
        private IQoSProvider _qoSProvider;
 | 
			
		||||
        private readonly QosProviderHouse _qosProviderHouse;
 | 
			
		||||
        private Response<IQoSProvider> _getResult;
 | 
			
		||||
        private DownstreamReRoute _reRoute;
 | 
			
		||||
        private readonly Mock<IQoSProviderFactory> _factory;
 | 
			
		||||
 | 
			
		||||
        public QosProviderHouseTests()
 | 
			
		||||
        {
 | 
			
		||||
            _factory = new Mock<IQoSProviderFactory>();
 | 
			
		||||
            _qosProviderHouse = new QosProviderHouse(_factory.Object);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_store_qos_provider_on_first_request()
 | 
			
		||||
        {
 | 
			
		||||
            var qosOptions = new QoSOptionsBuilder()
 | 
			
		||||
                .WithKey("test")
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var reRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithQosOptions(qosOptions)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
 | 
			
		||||
                .Then(x => x.ThenItIsAdded())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_not_store_qos_provider_on_first_request()
 | 
			
		||||
        {
 | 
			
		||||
            var qosOptions = new QoSOptionsBuilder()
 | 
			
		||||
                .WithKey("test")
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var reRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithQosOptions(qosOptions)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
 | 
			
		||||
                .When(x => x.WhenWeGetTheQoSProvider(reRoute))
 | 
			
		||||
                .Then(x => x.ThenItIsReturned())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_store_qos_providers_by_key()
 | 
			
		||||
        {
 | 
			
		||||
            var qosOptions = new QoSOptionsBuilder()
 | 
			
		||||
                .WithKey("test")
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var qosOptionsTwo = new QoSOptionsBuilder()
 | 
			
		||||
                .WithKey("testTwo")
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var reRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithQosOptions(qosOptions)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var reRouteTwo = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithQosOptions(qosOptionsTwo)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
 | 
			
		||||
                .And(x => x.GivenThereIsAQoSProvider(reRouteTwo, new FakePollyQoSProvider()))
 | 
			
		||||
                .When(x => x.WhenWeGetTheQoSProvider(reRoute))
 | 
			
		||||
                .Then(x => x.ThenTheQoSProviderIs<FakeQoSProvider>())
 | 
			
		||||
                .When(x => x.WhenWeGetTheQoSProvider(reRouteTwo))
 | 
			
		||||
                .Then(x => x.ThenTheQoSProviderIs<FakePollyQoSProvider>())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_error_if_no_qos_provider_with_key()
 | 
			
		||||
        {
 | 
			
		||||
            var qosOptions = new QoSOptionsBuilder()
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var reRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithQosOptions(qosOptions)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.When(x => x.WhenWeGetTheQoSProvider(reRoute))
 | 
			
		||||
            .Then(x => x.ThenAnErrorIsReturned())
 | 
			
		||||
            .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_get_new_qos_provider_if_reroute_qos_provider_has_changed()
 | 
			
		||||
        {
 | 
			
		||||
            var useQoSOptions = new QoSOptionsBuilder()
 | 
			
		||||
                .WithTimeoutValue(1)
 | 
			
		||||
                .WithKey("test")
 | 
			
		||||
                .WithDurationOfBreak(1)
 | 
			
		||||
                .WithExceptionsAllowedBeforeBreaking(1)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var dontUseQoSOptions = new QoSOptionsBuilder()
 | 
			
		||||
                .WithKey("test")
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var reRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithQosOptions(dontUseQoSOptions)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            var reRouteTwo = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithQosOptions(useQoSOptions)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
 | 
			
		||||
                .When(x => x.WhenWeGetTheQoSProvider(reRoute))
 | 
			
		||||
                .Then(x => x.ThenTheQoSProviderIs<FakeQoSProvider>())
 | 
			
		||||
                .When(x => x.WhenIGetTheReRouteWithTheSameKeyButDifferentQosProvider(reRouteTwo))
 | 
			
		||||
                .Then(x => x.ThenTheQoSProviderIs<FakePollyQoSProvider>())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIGetTheReRouteWithTheSameKeyButDifferentQosProvider(DownstreamReRoute reRoute)
 | 
			
		||||
        {
 | 
			
		||||
            _reRoute = reRoute;
 | 
			
		||||
            _factory.Setup(x => x.Get(_reRoute)).Returns(new FakePollyQoSProvider());
 | 
			
		||||
            _getResult = _qosProviderHouse.Get(_reRoute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenAnErrorIsReturned()
 | 
			
		||||
        {
 | 
			
		||||
            _getResult.IsError.ShouldBeTrue();
 | 
			
		||||
            _getResult.Errors[0].ShouldBeOfType<UnableToFindQoSProviderError>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheQoSProviderIs<T>()
 | 
			
		||||
        {
 | 
			
		||||
            _getResult.Data.ShouldBeOfType<T>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenItIsAdded()
 | 
			
		||||
        {
 | 
			
		||||
            _getResult.IsError.ShouldBe(false);
 | 
			
		||||
            _getResult.ShouldBeOfType<OkResponse<IQoSProvider>>();
 | 
			
		||||
            _factory.Verify(x => x.Get(_reRoute), Times.Once);
 | 
			
		||||
            _getResult.Data.ShouldBe(_qoSProvider);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenThereIsAQoSProvider(DownstreamReRoute reRoute, IQoSProvider qoSProvider)
 | 
			
		||||
        {
 | 
			
		||||
            _reRoute = reRoute;
 | 
			
		||||
            _qoSProvider = qoSProvider;
 | 
			
		||||
            _factory.Setup(x => x.Get(_reRoute)).Returns(_qoSProvider);
 | 
			
		||||
            _getResult = _qosProviderHouse.Get(reRoute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenWeGetTheQoSProvider(DownstreamReRoute reRoute)
 | 
			
		||||
        {
 | 
			
		||||
            _getResult = _qosProviderHouse.Get(reRoute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenItIsReturned()
 | 
			
		||||
        {
 | 
			
		||||
            _getResult.Data.ShouldBe(_qoSProvider);
 | 
			
		||||
            _factory.Verify(x => x.Get(_reRoute), Times.Once);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class FakeQoSProvider : IQoSProvider
 | 
			
		||||
        {
 | 
			
		||||
            T IQoSProvider.CircuitBreaker<T>()
 | 
			
		||||
            {
 | 
			
		||||
                throw new System.NotImplementedException();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        class FakePollyQoSProvider : IQoSProvider
 | 
			
		||||
        {
 | 
			
		||||
            T IQoSProvider.CircuitBreaker<T>()
 | 
			
		||||
            {
 | 
			
		||||
                throw new System.NotImplementedException();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
		Reference in New Issue
	
	Block a user