using System.Collections.Generic; using Moq; using Ocelot.Configuration; using Ocelot.Configuration.Builder; using Ocelot.Configuration.Provider; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.Responses; using Shouldly; using TestStack.BDDfy; using Xunit; namespace Ocelot.UnitTests.DownstreamRouteFinder { public class DownstreamRouteFinderTests { private readonly IDownstreamRouteFinder _downstreamRouteFinder; private readonly Mock _mockConfig; private readonly Mock _mockMatcher; private readonly Mock _finder; private string _upstreamUrlPath; private Response _result; private List _reRoutesConfig; private Response _match; private string _upstreamHttpMethod; public DownstreamRouteFinderTests() { _mockConfig = new Mock(); _mockMatcher = new Mock(); _finder = new Mock(); _downstreamRouteFinder = new Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object, _finder.Object); } [Fact] public void should_return_route() { this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher")) .And(x =>x.GivenTheTemplateVariableAndNameFinderReturns( new OkResponse>( new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod("Get") .WithUpstreamTemplatePattern("someUpstreamPath") .Build() }, string.Empty )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .When(x => x.WhenICallTheFinder()) .Then( x => x.ThenTheFollowingIsReturned(new DownstreamRoute( new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamHttpMethod("Get") .Build() ))) .And(x => x.ThenTheUrlMatcherIsCalledCorrectly()) .BDDfy(); } [Fact] public void should_return_route_if_upstream_path_and_upstream_template_are_the_same() { this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) .And( x => x.GivenTheTemplateVariableAndNameFinderReturns( new OkResponse>(new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod("Get") .WithUpstreamTemplatePattern("someUpstreamPath") .Build() }, string.Empty )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .When(x => x.WhenICallTheFinder()) .Then( x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamHttpMethod("Get") .Build() ))) .And(x => x.ThenTheUrlMatcherIsNotCalled()) .BDDfy(); } [Fact] public void should_return_correct_route_for_http_verb() { this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) .And( x => x.GivenTheTemplateVariableAndNameFinderReturns( new OkResponse>(new List()))) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPath") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod("Get") .WithUpstreamTemplatePattern("") .Build(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPathForAPost") .WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamHttpMethod("Post") .WithUpstreamTemplatePattern("") .Build() }, string.Empty )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) .When(x => x.WhenICallTheFinder()) .Then( x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List(), new ReRouteBuilder() .WithDownstreamPathTemplate("someDownstreamPathForAPost") .WithUpstreamHttpMethod("Post") .Build() ))) .BDDfy(); } [Fact] public void should_not_return_route() { this.Given(x => x.GivenThereIsAnUpstreamUrlPath("dontMatchPath")) .And(x => x.GivenTheConfigurationIs(new List { new ReRouteBuilder() .WithDownstreamPathTemplate("somPath") .WithUpstreamPathTemplate("somePath") .WithUpstreamHttpMethod("Get") .WithUpstreamTemplatePattern("somePath") .Build(), }, string.Empty )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(false)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .When(x => x.WhenICallTheFinder()) .Then( x => x.ThenAnErrorResponseIsReturned()) .And(x => x.ThenTheUrlMatcherIsCalledCorrectly()) .BDDfy(); } private void GivenTheTemplateVariableAndNameFinderReturns(Response> response) { _finder .Setup(x => x.Find(It.IsAny(), It.IsAny())) .Returns(response); } private void GivenTheUpstreamHttpMethodIs(string upstreamHttpMethod) { _upstreamHttpMethod = upstreamHttpMethod; } private void ThenAnErrorResponseIsReturned() { _result.IsError.ShouldBeTrue(); } private void ThenTheUrlMatcherIsCalledCorrectly() { _mockMatcher .Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Once); } private void ThenTheUrlMatcherIsNotCalled() { _mockMatcher .Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Never); } private void GivenTheUrlMatcherReturns(Response match) { _match = match; _mockMatcher .Setup(x => x.Match(It.IsAny(), It.IsAny())) .Returns(_match); } private void GivenTheConfigurationIs(List reRoutesConfig, string adminPath) { _reRoutesConfig = reRoutesConfig; _mockConfig .Setup(x => x.Get()) .ReturnsAsync(new OkResponse(new OcelotConfiguration(_reRoutesConfig, adminPath))); } private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) { _upstreamUrlPath = upstreamUrlPath; } private void WhenICallTheFinder() { _result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath, _upstreamHttpMethod).Result; } private void ThenTheFollowingIsReturned(DownstreamRoute expected) { _result.Data.ReRoute.DownstreamPathTemplate.Value.ShouldBe(expected.ReRoute.DownstreamPathTemplate.Value); for (int i = 0; i < _result.Data.TemplatePlaceholderNameAndValues.Count; i++) { _result.Data.TemplatePlaceholderNameAndValues[i].TemplateVariableName.ShouldBe( expected.TemplatePlaceholderNameAndValues[i].TemplateVariableName); _result.Data.TemplatePlaceholderNameAndValues[i].TemplateVariableValue.ShouldBe( expected.TemplatePlaceholderNameAndValues[i].TemplateVariableValue); } _result.IsError.ShouldBeFalse(); } } }