From 0627e9399be69c7d0a23e3ffb7b7f2593fd571ee Mon Sep 17 00:00:00 2001 From: TomPallister Date: Tue, 13 Sep 2016 20:29:00 +0100 Subject: [PATCH] brought in flurl and stated adding tests for the requester --- .../Requester/HttpClientHttpRequester.cs | 14 +-- .../Requester/IHttpRequester.cs | 5 +- .../Responder/HttpContextResponder.cs | 2 +- .../Responder/IHttpResponder.cs | 2 +- .../Middleware/ProxyMiddleware.cs | 4 +- .../ConfigurationValidationTests.cs | 10 +- .../DownstreamRouteFinderTests.cs | 21 ++-- .../Requester/RequesterTests.cs | 119 ++++++++++++++++++ .../Responder/ResponderTests.cs | 14 +++ .../UrlPathToUrlTemplateMatcherTests.cs | 5 +- ...eamUrlPathTemplateVariableReplacerTests.cs | 5 +- 11 files changed, 163 insertions(+), 38 deletions(-) rename test/Ocelot.UnitTests/{ => Configuration}/ConfigurationValidationTests.cs (84%) rename test/Ocelot.UnitTests/{ => DownstreamRouteFinder}/DownstreamRouteFinderTests.cs (83%) create mode 100644 test/Ocelot.UnitTests/Requester/RequesterTests.cs create mode 100644 test/Ocelot.UnitTests/Responder/ResponderTests.cs rename test/Ocelot.UnitTests/{ => UrlMatcher}/UrlPathToUrlTemplateMatcherTests.cs (99%) rename test/Ocelot.UnitTests/{ => UrlTemplateReplacer}/UpstreamUrlPathTemplateVariableReplacerTests.cs (98%) diff --git a/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs b/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs index 1b76ba8c..0f3bbbec 100644 --- a/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs +++ b/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs @@ -1,21 +1,17 @@ -using System.Net.Http; +using System.IO; +using System.Net.Http; using System.Threading.Tasks; +using Flurl.Http; namespace Ocelot.Library.Infrastructure.Requester { public class HttpClientHttpRequester : IHttpRequester { - public async Task GetResponse(string httpMethod, string downstreamUrl) + public async Task GetResponse(string httpMethod, string downstreamUrl, Stream content = null) { var method = new HttpMethod(httpMethod); - var httpRequestMessage = new HttpRequestMessage(method, downstreamUrl); - - using (var httpClient = new HttpClient()) - { - var response = await httpClient.SendAsync(httpRequestMessage); - return response; - } + return await downstreamUrl.SendAsync(method, new StreamContent(content)); } } } \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs b/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs index 310f25b3..9d38cc25 100644 --- a/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs +++ b/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs @@ -1,4 +1,5 @@ -using System.Net.Http; +using System.IO; +using System.Net.Http; using System.Threading.Tasks; using Flurl.Http; @@ -6,6 +7,6 @@ namespace Ocelot.Library.Infrastructure.Requester { public interface IHttpRequester { - Task GetResponse(string httpMethod, string downstreamUrl); + Task GetResponse(string httpMethod, string downstreamUrl, Stream content = null); } } diff --git a/src/Ocelot.Library/Infrastructure/Responder/HttpContextResponder.cs b/src/Ocelot.Library/Infrastructure/Responder/HttpContextResponder.cs index fed95e9e..1569e58a 100644 --- a/src/Ocelot.Library/Infrastructure/Responder/HttpContextResponder.cs +++ b/src/Ocelot.Library/Infrastructure/Responder/HttpContextResponder.cs @@ -7,7 +7,7 @@ namespace Ocelot.Library.Infrastructure.Responder { public class HttpContextResponder : IHttpResponder { - public async Task CreateSuccessResponse(HttpContext context, HttpResponseMessage response) + public async Task CreateResponse(HttpContext context, HttpResponseMessage response) { if (response.IsSuccessStatusCode) { diff --git a/src/Ocelot.Library/Infrastructure/Responder/IHttpResponder.cs b/src/Ocelot.Library/Infrastructure/Responder/IHttpResponder.cs index 3e2dc91b..97bb4995 100644 --- a/src/Ocelot.Library/Infrastructure/Responder/IHttpResponder.cs +++ b/src/Ocelot.Library/Infrastructure/Responder/IHttpResponder.cs @@ -6,7 +6,7 @@ namespace Ocelot.Library.Infrastructure.Responder { public interface IHttpResponder { - Task CreateSuccessResponse(HttpContext context, HttpResponseMessage response); + Task CreateResponse(HttpContext context, HttpResponseMessage response); Task CreateNotFoundResponse(HttpContext context); } diff --git a/src/Ocelot.Library/Middleware/ProxyMiddleware.cs b/src/Ocelot.Library/Middleware/ProxyMiddleware.cs index 31b7c487..9eb93e07 100644 --- a/src/Ocelot.Library/Middleware/ProxyMiddleware.cs +++ b/src/Ocelot.Library/Middleware/ProxyMiddleware.cs @@ -47,9 +47,9 @@ namespace Ocelot.Library.Middleware var downstreamUrl = _urlReplacer.ReplaceTemplateVariables(downstreamRoute.Data); - var response = await _requester.GetResponse(context.Request.Method, downstreamUrl); + var response = await _requester.GetResponse(context.Request.Method, downstreamUrl, context.Request.Body); - context = await _responder.CreateSuccessResponse(context, response); + await _responder.CreateResponse(context, response); await _next.Invoke(context); } diff --git a/test/Ocelot.UnitTests/ConfigurationValidationTests.cs b/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs similarity index 84% rename from test/Ocelot.UnitTests/ConfigurationValidationTests.cs rename to test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs index 615e6e90..3ddc8d38 100644 --- a/test/Ocelot.UnitTests/ConfigurationValidationTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ConfigurationValidationTests.cs @@ -5,11 +5,11 @@ using Shouldly; using TestStack.BDDfy; using Xunit; -namespace Ocelot.UnitTests +namespace Ocelot.UnitTests.Configuration { public class ConfigurationValidationTests { - private Configuration _configuration; + private Library.Infrastructure.Configuration.Configuration _configuration; private readonly IConfigurationValidator _configurationValidator; private Response _result; @@ -21,7 +21,7 @@ namespace Ocelot.UnitTests [Fact] public void configuration_is_valid_with_one_reroute() { - this.Given(x => x.GivenAConfiguration(new Configuration() + this.Given(x => x.GivenAConfiguration(new Library.Infrastructure.Configuration.Configuration() { ReRoutes = new List { @@ -40,7 +40,7 @@ namespace Ocelot.UnitTests [Fact] public void configuration_is_not_valid_with_duplicate_reroutes() { - this.Given(x => x.GivenAConfiguration(new Configuration() + this.Given(x => x.GivenAConfiguration(new Library.Infrastructure.Configuration.Configuration() { ReRoutes = new List { @@ -62,7 +62,7 @@ namespace Ocelot.UnitTests .BDDfy(); } - private void GivenAConfiguration(Configuration configuration) + private void GivenAConfiguration(Library.Infrastructure.Configuration.Configuration configuration) { _configuration = configuration; } diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinderTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs similarity index 83% rename from test/Ocelot.UnitTests/DownstreamRouteFinderTests.cs rename to test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs index 1f796adb..6d115a66 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinderTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Collections.Generic; using Microsoft.Extensions.Options; using Moq; using Ocelot.Library.Infrastructure.Configuration; @@ -12,31 +9,31 @@ using Shouldly; using TestStack.BDDfy; using Xunit; -namespace Ocelot.UnitTests +namespace Ocelot.UnitTests.DownstreamRouteFinder { public class DownstreamRouteFinderTests { private readonly IDownstreamRouteFinder _downstreamRouteFinder; - private readonly Mock> _mockConfig; + private readonly Mock> _mockConfig; private readonly Mock _mockMatcher; private string _upstreamUrlPath; private Response _result; private Response _response; - private Configuration _configuration; + private Library.Infrastructure.Configuration.Configuration _configuration; private UrlMatch _match; public DownstreamRouteFinderTests() { - _mockConfig = new Mock>(); + _mockConfig = new Mock>(); _mockMatcher = new Mock(); - _downstreamRouteFinder = new DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object); + _downstreamRouteFinder = new Library.Infrastructure.DownstreamRouteFinder.DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object); } [Fact] public void should_return_route() { this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) - .And(x => x.GivenTheConfigurationIs(new Configuration { + .And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration { ReRoutes = new List { new ReRoute() @@ -58,7 +55,7 @@ namespace Ocelot.UnitTests public void should_not_return_route() { this.Given(x => x.GivenThereIsAnUpstreamUrlPath("somePath")) - .And(x => x.GivenTheConfigurationIs(new Configuration + .And(x => x.GivenTheConfigurationIs(new Library.Infrastructure.Configuration.Configuration { ReRoutes = new List { @@ -96,7 +93,7 @@ namespace Ocelot.UnitTests .Returns(_match); } - private void GivenTheConfigurationIs(Configuration configuration) + private void GivenTheConfigurationIs(Library.Infrastructure.Configuration.Configuration configuration) { _configuration = configuration; _mockConfig diff --git a/test/Ocelot.UnitTests/Requester/RequesterTests.cs b/test/Ocelot.UnitTests/Requester/RequesterTests.cs new file mode 100644 index 00000000..dd9d86d4 --- /dev/null +++ b/test/Ocelot.UnitTests/Requester/RequesterTests.cs @@ -0,0 +1,119 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Flurl.Http.Testing; +using Ocelot.Library.Infrastructure.Requester; +using Shouldly; +using TestStack.BDDfy; +using Xunit; + +namespace Ocelot.UnitTests.Requester +{ + public class RequesterTests : IDisposable + { + private readonly IHttpRequester _httpRequester; + private readonly HttpTest _httpTest; + private string _httpMethod; + private string _downstreamUrl; + private HttpResponseMessage _result; + private HttpContent _content; + + public RequesterTests() + { + _httpTest = new HttpTest(); + _httpRequester = new HttpClientHttpRequester(); + } + + [Fact] + public void should_call_downstream_url_correctly() + { + this.Given(x => x.GivenIHaveHttpMethod("GET")) + .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) + .And(x => x.GivenTheDownstreamServerReturns(HttpStatusCode.OK)) + .When(x => x.WhenIMakeARequest()) + .Then(x => x.ThenTheFollowingIsReturned(HttpStatusCode.OK)) + .And(x => x.ThenTheDownstreamServerIsCalledCorrectly()) + .BDDfy(); + } + + [Fact] + public void should_obey_http_method() + { + this.Given(x => x.GivenIHaveHttpMethod("POST")) + .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) + .And(x => x.GivenTheDownstreamServerReturns(HttpStatusCode.Created)) + .When(x => x.WhenIMakeARequest()) + .Then(x => x.ThenTheFollowingIsReturned(HttpStatusCode.Created)) + .And(x => x.ThenTheDownstreamServerIsCalledCorrectly()) + .And(x => x.ThenTheCorrectHttpMethodIsUsed(HttpMethod.Post)) + .BDDfy(); + } + + [Fact] + public void should_forward_http_content() + { + this.Given(x => x.GivenIHaveHttpMethod("POST")) + .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) + .And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom"))) + .And(x => x.GivenTheDownstreamServerReturns(HttpStatusCode.Created)) + .When(x => x.WhenIMakeARequest()) + .Then(x => x.ThenTheFollowingIsReturned(HttpStatusCode.Created)) + .And(x => x.ThenTheDownstreamServerIsCalledCorrectly()) + .And(x => x.ThenTheCorrectHttpMethodIsUsed(HttpMethod.Post)) + .And(x => x.ThenTheCorrectContentIsUsed(new StringContent("Hi from Tom"))) + .BDDfy(); + } + + private void GivenIHaveTheHttpContent(HttpContent content) + { + _content = content; + } + + private void GivenIHaveHttpMethod(string httpMethod) + { + _httpMethod = httpMethod; + } + + private void GivenIHaveDownstreamUrl(string downstreamUrl) + { + _downstreamUrl = downstreamUrl; + } + + private void GivenTheDownstreamServerReturns(HttpStatusCode statusCode) + { + _httpTest.RespondWith(_content != null ? _content.ReadAsStringAsync().Result : string.Empty, (int)statusCode); + } + + private void WhenIMakeARequest() + { + _result = _httpRequester.GetResponse(_httpMethod, _downstreamUrl, _content != null ? _content.ReadAsStreamAsync().Result : Stream.Null).Result; + } + + private void ThenTheFollowingIsReturned(HttpStatusCode expected) + { + _result.StatusCode.ShouldBe(expected); + } + + private void ThenTheDownstreamServerIsCalledCorrectly() + { + _httpTest.ShouldHaveCalled(_downstreamUrl); + } + + private void ThenTheCorrectHttpMethodIsUsed(HttpMethod expected) + { + _httpTest.CallLog[0].Request.Method.ShouldBe(expected); + } + + private void ThenTheCorrectContentIsUsed(HttpContent content) + { + _httpTest.CallLog[0].Response.Content.ReadAsStringAsync().Result.ShouldBe(content.ReadAsStringAsync().Result); + } + + public void Dispose() + { + _httpTest.Dispose(); + } + } +} diff --git a/test/Ocelot.UnitTests/Responder/ResponderTests.cs b/test/Ocelot.UnitTests/Responder/ResponderTests.cs new file mode 100644 index 00000000..60a20153 --- /dev/null +++ b/test/Ocelot.UnitTests/Responder/ResponderTests.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Http; +using Xunit; + +namespace Ocelot.UnitTests.Responder +{ + public class ResponderTests + { + [Fact] + public void should_do_something() + { + + } + } +} diff --git a/test/Ocelot.UnitTests/UrlPathToUrlTemplateMatcherTests.cs b/test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs similarity index 99% rename from test/Ocelot.UnitTests/UrlPathToUrlTemplateMatcherTests.cs rename to test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs index eb3ff139..c2f64419 100644 --- a/test/Ocelot.UnitTests/UrlPathToUrlTemplateMatcherTests.cs +++ b/test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs @@ -2,12 +2,11 @@ using System.Collections.Generic; using System.Linq; using Ocelot.Library.Infrastructure.UrlMatcher; using Shouldly; +using TestStack.BDDfy; using Xunit; -namespace Ocelot.UnitTests +namespace Ocelot.UnitTests.UrlMatcher { - using TestStack.BDDfy; - public class UrlPathToUrlTemplateMatcherTests { private readonly IUrlPathToUrlTemplateMatcher _urlMatcher; diff --git a/test/Ocelot.UnitTests/UpstreamUrlPathTemplateVariableReplacerTests.cs b/test/Ocelot.UnitTests/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs similarity index 98% rename from test/Ocelot.UnitTests/UpstreamUrlPathTemplateVariableReplacerTests.cs rename to test/Ocelot.UnitTests/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs index 64bd0a1f..ef03aa70 100644 --- a/test/Ocelot.UnitTests/UpstreamUrlPathTemplateVariableReplacerTests.cs +++ b/test/Ocelot.UnitTests/UrlTemplateReplacer/UpstreamUrlPathTemplateVariableReplacerTests.cs @@ -3,12 +3,11 @@ using Ocelot.Library.Infrastructure.DownstreamRouteFinder; using Ocelot.Library.Infrastructure.UrlMatcher; using Ocelot.Library.Infrastructure.UrlTemplateReplacer; using Shouldly; +using TestStack.BDDfy; using Xunit; -namespace Ocelot.UnitTests +namespace Ocelot.UnitTests.UrlTemplateReplacer { - using TestStack.BDDfy; - public class UpstreamUrlPathTemplateVariableReplacerTests { private DownstreamRoute _downstreamRoute;