wip tests failing

This commit is contained in:
TomPallister 2020-11-27 19:01:27 +00:00
parent 6eed692c29
commit 32551624bb
19 changed files with 1104 additions and 1068 deletions

View File

@ -1,35 +1,35 @@
namespace Ocelot.Provider.Eureka namespace Ocelot.Provider.Eureka
{ {
using ServiceDiscovery.Providers; using Ocelot.ServiceDiscovery.Providers;
using Steeltoe.Common.Discovery; using Steeltoe.Discovery;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Values; using Ocelot.Values;
public class Eureka : IServiceDiscoveryProvider public class Eureka : IServiceDiscoveryProvider
{ {
private readonly IDiscoveryClient _client; private readonly IDiscoveryClient _client;
private readonly string _serviceName; private readonly string _serviceName;
public Eureka(string serviceName, IDiscoveryClient client) public Eureka(string serviceName, IDiscoveryClient client)
{ {
_client = client; _client = client;
_serviceName = serviceName; _serviceName = serviceName;
} }
public Task<List<Service>> Get() public Task<List<Service>> Get()
{ {
var services = new List<Service>(); var services = new List<Service>();
var instances = _client.GetInstances(_serviceName); var instances = _client.GetInstances(_serviceName);
if (instances != null && instances.Any()) if (instances != null && instances.Any())
{ {
services.AddRange(instances.Select(i => new Service(i.ServiceId, new ServiceHostAndPort(i.Host, i.Port, i.Uri.Scheme), "", "", new List<string>()))); services.AddRange(instances.Select(i => new Service(i.ServiceId, new ServiceHostAndPort(i.Host, i.Port, i.Uri.Scheme), "", "", new List<string>())));
} }
return Task.FromResult(services); return Task.FromResult(services);
} }
} }
} }

View File

@ -1,9 +1,9 @@
namespace Ocelot.Provider.Eureka namespace Ocelot.Provider.Eureka
{ {
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using ServiceDiscovery; using Ocelot.ServiceDiscovery;
using Steeltoe.Common.Discovery; using Steeltoe.Discovery;
public static class EurekaProviderFactory public static class EurekaProviderFactory
{ {
public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) => public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>

View File

@ -27,7 +27,7 @@
<ProjectReference Include="..\Ocelot\Ocelot.csproj" /> <ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.4.2" /> <PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164"> <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>

View File

@ -96,8 +96,13 @@ namespace Ocelot.AcceptanceTests
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/users")) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/users"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("UserId: 1231231")) .And(x => _steps.ThenTheResponseBodyShouldBe("UserId: 1231231"))
.And(x => _downstreamFinalPath.ShouldBe("/users/1231231")) .And(x => ThenTheDownstreamPathIs("/users/1231231"))
.BDDfy(); .BDDfy();
}
private void ThenTheDownstreamPathIs(string path)
{
_downstreamFinalPath.ShouldBe(path);
} }
private void GivenThereIsAServiceRunningOn(string url, int statusCode) private void GivenThereIsAServiceRunningOn(string url, int statusCode)

View File

@ -1,60 +1,60 @@
using IdentityServer4.AccessTokenValidation; using IdentityServer4.AccessTokenValidation;
using IdentityServer4.Models; using IdentityServer4.Models;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Security.Claims; using System.Security.Claims;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
namespace Ocelot.AcceptanceTests namespace Ocelot.AcceptanceTests
{ {
using IdentityServer4.Test; using IdentityServer4.Test;
using Shouldly; using Shouldly;
public class ClaimsToQueryStringForwardingTests : IDisposable public class ClaimsToQueryStringForwardingTests : IDisposable
{ {
private IWebHost _servicebuilder; private IWebHost _servicebuilder;
private IWebHost _identityServerBuilder; private IWebHost _identityServerBuilder;
private readonly Steps _steps; private readonly Steps _steps;
private Action<IdentityServerAuthenticationOptions> _options; private Action<IdentityServerAuthenticationOptions> _options;
private string _identityServerRootUrl; private string _identityServerRootUrl;
private string _downstreamQueryString; private string _downstreamQueryString;
public ClaimsToQueryStringForwardingTests() public ClaimsToQueryStringForwardingTests()
{ {
_steps = new Steps(); _steps = new Steps();
var identityServerPort = RandomPortFinder.GetRandomPort(); var identityServerPort = RandomPortFinder.GetRandomPort();
_identityServerRootUrl = $"http://localhost:{identityServerPort}"; _identityServerRootUrl = $"http://localhost:{identityServerPort}";
_options = o => _options = o =>
{ {
o.Authority = _identityServerRootUrl; o.Authority = _identityServerRootUrl;
o.ApiName = "api"; o.ApiName = "api";
o.RequireHttpsMetadata = false; o.RequireHttpsMetadata = false;
o.SupportedTokens = SupportedTokens.Both; o.SupportedTokens = SupportedTokens.Both;
o.ApiSecret = "secret"; o.ApiSecret = "secret";
}; };
} }
[Fact] [Fact]
public void should_return_response_200_and_foward_claim_as_query_string() public void should_return_response_200_and_foward_claim_as_query_string()
{ {
var user = new TestUser() var user = new TestUser()
{ {
Username = "test", Username = "test",
Password = "test", Password = "test",
SubjectId = "registered|1231231", SubjectId = "registered|1231231",
Claims = new List<Claim> Claims = new List<Claim>
{ {
new Claim("CustomerId", "123"), new Claim("CustomerId", "123"),
new Claim("LocationId", "1") new Claim("LocationId", "1")
} }
}; };
@ -62,38 +62,38 @@ namespace Ocelot.AcceptanceTests
var configuration = new FileConfiguration var configuration = new FileConfiguration
{ {
Routes = new List<FileRoute> Routes = new List<FileRoute>
{ {
new FileRoute new FileRoute
{ {
DownstreamPathTemplate = "/", DownstreamPathTemplate = "/",
DownstreamHostAndPorts = new List<FileHostAndPort> DownstreamHostAndPorts = new List<FileHostAndPort>
{ {
new FileHostAndPort new FileHostAndPort
{ {
Host = "localhost", Host = "localhost",
Port = port, Port = port,
} }
}, },
DownstreamScheme = "http", DownstreamScheme = "http",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" }, UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AuthenticationProviderKey = "Test", AuthenticationProviderKey = "Test",
AllowedScopes = new List<string> AllowedScopes = new List<string>
{ {
"openid", "offline_access", "api" "openid", "offline_access", "api"
}, },
}, },
AddQueriesToRequest = AddQueriesToRequest =
{ {
{"CustomerId", "Claims[CustomerId] > value"}, {"CustomerId", "Claims[CustomerId] > value"},
{"LocationId", "Claims[LocationId] > value"}, {"LocationId", "Claims[LocationId] > value"},
{"UserType", "Claims[sub] > value[0] > |"}, {"UserType", "Claims[sub] > value[0] > |"},
{"UserId", "Claims[sub] > value[1] > |"} {"UserId", "Claims[sub] > value[1] > |"}
} }
} }
} }
}; };
@ -106,21 +106,21 @@ namespace Ocelot.AcceptanceTests
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231")) .And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231"))
.BDDfy(); .BDDfy();
} }
[Fact] [Fact]
public void should_return_response_200_and_foward_claim_as_query_string_and_preserve_original_string() public void should_return_response_200_and_foward_claim_as_query_string_and_preserve_original_string()
{ {
var user = new TestUser() var user = new TestUser()
{ {
Username = "test", Username = "test",
Password = "test", Password = "test",
SubjectId = "registered|1231231", SubjectId = "registered|1231231",
Claims = new List<Claim> Claims = new List<Claim>
{ {
new Claim("CustomerId", "123"), new Claim("CustomerId", "123"),
new Claim("LocationId", "1") new Claim("LocationId", "1")
} }
}; };
@ -128,38 +128,38 @@ namespace Ocelot.AcceptanceTests
var configuration = new FileConfiguration var configuration = new FileConfiguration
{ {
Routes = new List<FileRoute> Routes = new List<FileRoute>
{ {
new FileRoute new FileRoute
{ {
DownstreamPathTemplate = "/", DownstreamPathTemplate = "/",
DownstreamHostAndPorts = new List<FileHostAndPort> DownstreamHostAndPorts = new List<FileHostAndPort>
{ {
new FileHostAndPort new FileHostAndPort
{ {
Host = "localhost", Host = "localhost",
Port = port, Port = port,
} }
}, },
DownstreamScheme = "http", DownstreamScheme = "http",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" }, UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AuthenticationProviderKey = "Test", AuthenticationProviderKey = "Test",
AllowedScopes = new List<string> AllowedScopes = new List<string>
{ {
"openid", "offline_access", "api" "openid", "offline_access", "api"
}, },
}, },
AddQueriesToRequest = AddQueriesToRequest =
{ {
{"CustomerId", "Claims[CustomerId] > value"}, {"CustomerId", "Claims[CustomerId] > value"},
{"LocationId", "Claims[LocationId] > value"}, {"LocationId", "Claims[LocationId] > value"},
{"UserType", "Claims[sub] > value[0] > |"}, {"UserType", "Claims[sub] > value[0] > |"},
{"UserId", "Claims[sub] > value[1] > |"} {"UserId", "Claims[sub] > value[1] > |"}
} }
} }
} }
}; };
@ -172,120 +172,125 @@ namespace Ocelot.AcceptanceTests
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/?test=1&test=2")) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/?test=1&test=2"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231")) .And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231"))
.And(_ => _downstreamQueryString.ShouldBe("?test=1&test=2&CustomerId=123&LocationId=1&UserId=1231231&UserType=registered")) .And(_ => ThenTheQueryStringIs("?test=1&test=2&CustomerId=123&LocationId=1&UserId=1231231&UserType=registered"))
.BDDfy(); .BDDfy();
} }
private void GivenThereIsAServiceRunningOn(string url, int statusCode) private void ThenTheQueryStringIs(string queryString)
{ {
_servicebuilder = new WebHostBuilder() _downstreamQueryString.ShouldBe(queryString);
.UseUrls(url) }
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory()) private void GivenThereIsAServiceRunningOn(string url, int statusCode)
.UseIISIntegration() {
.UseUrls(url) _servicebuilder = new WebHostBuilder()
.Configure(app => .UseUrls(url)
{ .UseKestrel()
app.Run(async context => .UseContentRoot(Directory.GetCurrentDirectory())
{ .UseIISIntegration()
_downstreamQueryString = context.Request.QueryString.Value; .UseUrls(url)
.Configure(app =>
StringValues customerId; {
context.Request.Query.TryGetValue("CustomerId", out customerId); app.Run(async context =>
{
StringValues locationId; _downstreamQueryString = context.Request.QueryString.Value;
context.Request.Query.TryGetValue("LocationId", out locationId);
StringValues customerId;
StringValues userType; context.Request.Query.TryGetValue("CustomerId", out customerId);
context.Request.Query.TryGetValue("UserType", out userType);
StringValues locationId;
StringValues userId; context.Request.Query.TryGetValue("LocationId", out locationId);
context.Request.Query.TryGetValue("UserId", out userId);
StringValues userType;
var responseBody = $"CustomerId: {customerId} LocationId: {locationId} UserType: {userType} UserId: {userId}"; context.Request.Query.TryGetValue("UserType", out userType);
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody); StringValues userId;
}); context.Request.Query.TryGetValue("UserId", out userId);
})
.Build(); var responseBody = $"CustomerId: {customerId} LocationId: {locationId} UserType: {userType} UserId: {userId}";
context.Response.StatusCode = statusCode;
_servicebuilder.Start(); await context.Response.WriteAsync(responseBody);
} });
})
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user) .Build();
{
_identityServerBuilder = new WebHostBuilder() _servicebuilder.Start();
.UseUrls(url) }
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory()) private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user)
.UseIISIntegration() {
.UseUrls(url) _identityServerBuilder = new WebHostBuilder()
.ConfigureServices(services => .UseUrls(url)
{ .UseKestrel()
services.AddLogging(); .UseContentRoot(Directory.GetCurrentDirectory())
services.AddIdentityServer() .UseIISIntegration()
.AddDeveloperSigningCredential() .UseUrls(url)
.AddInMemoryApiResources(new List<ApiResource> .ConfigureServices(services =>
{ {
new ApiResource services.AddLogging();
{ services.AddIdentityServer()
Name = apiName, .AddDeveloperSigningCredential()
Description = "My API", .AddInMemoryApiResources(new List<ApiResource>
Enabled = true, {
DisplayName = "test", new ApiResource
Scopes = new List<Scope>() {
{ Name = apiName,
new Scope("api"), Description = "My API",
new Scope("openid"), Enabled = true,
new Scope("offline_access") DisplayName = "test",
}, Scopes = new List<Scope>()
ApiSecrets = new List<Secret>() {
{ new Scope("api"),
new Secret new Scope("openid"),
{ new Scope("offline_access")
Value = "secret".Sha256() },
} ApiSecrets = new List<Secret>()
}, {
UserClaims = new List<string>() new Secret
{ {
"CustomerId", "LocationId", "UserType", "UserId" Value = "secret".Sha256()
} }
} },
}) UserClaims = new List<string>()
.AddInMemoryClients(new List<Client> {
{ "CustomerId", "LocationId", "UserType", "UserId"
new Client }
{ }
ClientId = "client", })
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, .AddInMemoryClients(new List<Client>
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())}, {
AllowedScopes = new List<string> { apiName, "openid", "offline_access" }, new Client
AccessTokenType = tokenType, {
Enabled = true, ClientId = "client",
RequireClientSecret = false AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
} ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
}) AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
.AddTestUsers(new List<TestUser> AccessTokenType = tokenType,
{ Enabled = true,
user RequireClientSecret = false
}); }
}) })
.Configure(app => .AddTestUsers(new List<TestUser>
{ {
app.UseIdentityServer(); user
}) });
.Build(); })
.Configure(app =>
_identityServerBuilder.Start(); {
app.UseIdentityServer();
_steps.VerifyIdentiryServerStarted(url); })
} .Build();
public void Dispose() _identityServerBuilder.Start();
{
_servicebuilder?.Dispose(); _steps.VerifyIdentiryServerStarted(url);
_steps.Dispose(); }
_identityServerBuilder?.Dispose();
} public void Dispose()
} {
_servicebuilder?.Dispose();
_steps.Dispose();
_identityServerBuilder?.Dispose();
}
}
} }

View File

@ -62,7 +62,7 @@ namespace Ocelot.AcceptanceTests
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.And(x => cache.Count.ShouldBe(1)) .And(x => ThenTheCountShouldBe(cache, 1))
.BDDfy(); .BDDfy();
} }
@ -122,10 +122,15 @@ namespace Ocelot.AcceptanceTests
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.And(x => cache.Count.ShouldBe(2)) .And(x => ThenTheCountShouldBe(cache, 2))
.BDDfy(); .BDDfy();
} }
private void ThenTheCountShouldBe(FakeHttpClientCache cache, int count)
{
cache.Count.ShouldBe(count);
}
private void GivenThereIsAServiceRunningOn(string baseUrl, int statusCode, string responseBody) private void GivenThereIsAServiceRunningOn(string baseUrl, int statusCode, string responseBody)
{ {
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, async context => _serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, async context =>

View File

@ -46,7 +46,7 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164"> <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
@ -59,7 +59,7 @@
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" /> <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" /> <PackageReference Include="Shouldly" Version="4.0.1" />
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" /> <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
@ -68,7 +68,7 @@
<PackageReference Include="Consul" Version="1.6.1.1" /> <PackageReference Include="Consul" Version="1.6.1.1" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" /> <PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
<PackageReference Include="CacheManager.Serialization.Json" Version="2.0.0-beta-1629" /> <PackageReference Include="CacheManager.Serialization.Json" Version="2.0.0-beta-1629" />
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.4.2" /> <PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" /> <PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />

View File

@ -322,7 +322,7 @@
.When(_ => _steps.WhenIGetUrlOnTheApiGateway("/home")) .When(_ => _steps.WhenIGetUrlOnTheApiGateway("/home"))
.Then(_ => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .Then(_ => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(_ => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) .And(_ => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.And(_ => _receivedToken.ShouldBe(token)) .And(_ => ThenTheTokenIs(token))
.BDDfy(); .BDDfy();
} }
@ -462,6 +462,11 @@
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy(); .BDDfy();
}
private void ThenTheTokenIs(string token)
{
_receivedToken.ShouldBe(token);
} }
private void WhenIAddAServiceBackIn(ServiceEntry serviceEntryTwo) private void WhenIAddAServiceBackIn(ServiceEntry serviceEntryTwo)

View File

@ -57,7 +57,7 @@ namespace Ocelot.AcceptanceTests
.And(_ => _steps.StartFakeOcelotWithWebSockets()) .And(_ => _steps.StartFakeOcelotWithWebSockets())
.And(_ => StartFakeDownstreamService($"http://{downstreamHost}:{downstreamPort}", "/ws")) .And(_ => StartFakeDownstreamService($"http://{downstreamHost}:{downstreamPort}", "/ws"))
.When(_ => StartClient("ws://localhost:5000/")) .When(_ => StartClient("ws://localhost:5000/"))
.Then(_ => _firstRecieved.Count.ShouldBe(10)) .Then(_ => ThenTheReceivedCountIs(10))
.BDDfy(); .BDDfy();
} }
@ -323,8 +323,12 @@ namespace Ocelot.AcceptanceTests
{ {
Console.WriteLine(e); Console.WriteLine(e);
} }
}
private void ThenTheReceivedCountIs(int count)
{
_firstRecieved.Count.ShouldBe(count);
} }
public void Dispose() public void Dispose()
{ {
_serviceHandler?.Dispose(); _serviceHandler?.Dispose();

View File

@ -35,7 +35,7 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164"> <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
@ -48,7 +48,7 @@
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" /> <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" /> <PackageReference Include="Shouldly" Version="4.0.1" />
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" /> <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
<PackageReference Include="Microsoft.Data.SQLite" Version="5.0.0" /> <PackageReference Include="Microsoft.Data.SQLite" Version="5.0.0" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" /> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />

View File

@ -1,299 +1,304 @@
namespace Ocelot.UnitTests.Consul namespace Ocelot.UnitTests.Consul
{ {
using global::Consul; using global::Consul;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Moq; using Moq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ocelot.Logging; using Ocelot.Logging;
using Provider.Consul; using Provider.Consul;
using Shouldly; using Shouldly;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using TestStack.BDDfy; using TestStack.BDDfy;
using Values; using Values;
using Xunit; using Xunit;
public class ConsulServiceDiscoveryProviderTests : IDisposable public class ConsulServiceDiscoveryProviderTests : IDisposable
{ {
private IWebHost _fakeConsulBuilder; private IWebHost _fakeConsulBuilder;
private readonly List<ServiceEntry> _serviceEntries; private readonly List<ServiceEntry> _serviceEntries;
private Consul _provider; private Consul _provider;
private readonly string _serviceName; private readonly string _serviceName;
private readonly int _port; private readonly int _port;
private readonly string _consulHost; private readonly string _consulHost;
private readonly string _consulScheme; private readonly string _consulScheme;
private readonly string _fakeConsulServiceDiscoveryUrl; private readonly string _fakeConsulServiceDiscoveryUrl;
private List<Service> _services; private List<Service> _services;
private readonly Mock<IOcelotLoggerFactory> _factory; private readonly Mock<IOcelotLoggerFactory> _factory;
private readonly Mock<IOcelotLogger> _logger; private readonly Mock<IOcelotLogger> _logger;
private string _receivedToken; private string _receivedToken;
private readonly IConsulClientFactory _clientFactory; private readonly IConsulClientFactory _clientFactory;
public ConsulServiceDiscoveryProviderTests() public ConsulServiceDiscoveryProviderTests()
{ {
_serviceName = "test"; _serviceName = "test";
_port = 8500; _port = 8500;
_consulHost = "localhost"; _consulHost = "localhost";
_consulScheme = "http"; _consulScheme = "http";
_fakeConsulServiceDiscoveryUrl = $"{_consulScheme}://{_consulHost}:{_port}"; _fakeConsulServiceDiscoveryUrl = $"{_consulScheme}://{_consulHost}:{_port}";
_serviceEntries = new List<ServiceEntry>(); _serviceEntries = new List<ServiceEntry>();
_factory = new Mock<IOcelotLoggerFactory>(); _factory = new Mock<IOcelotLoggerFactory>();
_clientFactory = new ConsulClientFactory(); _clientFactory = new ConsulClientFactory();
_logger = new Mock<IOcelotLogger>(); _logger = new Mock<IOcelotLogger>();
_factory.Setup(x => x.CreateLogger<Consul>()).Returns(_logger.Object); _factory.Setup(x => x.CreateLogger<Consul>()).Returns(_logger.Object);
_factory.Setup(x => x.CreateLogger<PollConsul>()).Returns(_logger.Object); _factory.Setup(x => x.CreateLogger<PollConsul>()).Returns(_logger.Object);
var config = new ConsulRegistryConfiguration(_consulScheme, _consulHost, _port, _serviceName, null); var config = new ConsulRegistryConfiguration(_consulScheme, _consulHost, _port, _serviceName, null);
_provider = new Consul(config, _factory.Object, _clientFactory); _provider = new Consul(config, _factory.Object, _clientFactory);
}
[Fact]
public void should_return_service_from_consul()
{
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "localhost",
Port = 50881,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
.When(x => WhenIGetTheServices())
.Then(x => ThenTheCountIs(1))
.BDDfy();
}
[Fact]
public void should_use_token()
{
var token = "test token";
var config = new ConsulRegistryConfiguration(_consulScheme, _consulHost, _port, _serviceName, token);
_provider = new Consul(config, _factory.Object, _clientFactory);
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "localhost",
Port = 50881,
ID = Guid.NewGuid().ToString(),
Tags = new string[0],
},
};
this.Given(_ => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
.And(_ => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
.When(_ => WhenIGetTheServices())
.Then(_ => ThenTheCountIs(1))
.And(_ => ThenTheTokenIs(token))
.BDDfy();
}
[Fact]
public void should_not_return_services_with_invalid_address()
{
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "http://localhost",
Port = 50881,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
var serviceEntryTwo = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "http://localhost",
Port = 50888,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
.When(x => WhenIGetTheServices())
.Then(x => ThenTheCountIs(0))
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress())
.BDDfy();
}
[Fact]
public void should_not_return_services_with_empty_address()
{
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "",
Port = 50881,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
var serviceEntryTwo = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = null,
Port = 50888,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
.When(x => WhenIGetTheServices())
.Then(x => ThenTheCountIs(0))
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForEmptyAddress())
.BDDfy();
}
[Fact]
public void should_not_return_services_with_invalid_port()
{
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "localhost",
Port = -1,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
var serviceEntryTwo = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "localhost",
Port = 0,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
.When(x => WhenIGetTheServices())
.Then(x => ThenTheCountIs(0))
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts())
.BDDfy();
}
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress()
{
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: http://localhost and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: http://localhost and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
}
private void ThenTheLoggerHasBeenCalledCorrectlyForEmptyAddress()
{
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
}
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts()
{
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: localhost and Port: -1 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: localhost and Port: 0 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
}
private void ThenTheCountIs(int count)
{
_services.Count.ShouldBe(count);
}
private void WhenIGetTheServices()
{
_services = _provider.Get().GetAwaiter().GetResult();
} }
[Fact] private void ThenTheTokenIs(string token)
public void should_return_service_from_consul()
{ {
var serviceEntryOne = new ServiceEntry() _receivedToken.ShouldBe(token);
{ }
Service = new AgentService()
{ private void GivenTheServicesAreRegisteredWithConsul(params ServiceEntry[] serviceEntries)
Service = _serviceName, {
Address = "localhost", foreach (var serviceEntry in serviceEntries)
Port = 50881, {
ID = Guid.NewGuid().ToString(), _serviceEntries.Add(serviceEntry);
Tags = new string[0] }
}, }
};
private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url, string serviceName)
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName)) {
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne)) _fakeConsulBuilder = new WebHostBuilder()
.When(x => WhenIGetTheServices()) .UseUrls(url)
.Then(x => ThenTheCountIs(1)) .UseKestrel()
.BDDfy(); .UseContentRoot(Directory.GetCurrentDirectory())
} .UseIISIntegration()
.UseUrls(url)
[Fact] .Configure(app =>
public void should_use_token() {
{ app.Run(async context =>
var token = "test token"; {
var config = new ConsulRegistryConfiguration(_consulScheme, _consulHost, _port, _serviceName, token); if (context.Request.Path.Value == $"/v1/health/service/{serviceName}")
_provider = new Consul(config, _factory.Object, _clientFactory); {
if (context.Request.Headers.TryGetValue("X-Consul-Token", out var values))
var serviceEntryOne = new ServiceEntry() {
{ _receivedToken = values.First();
Service = new AgentService() }
{
Service = _serviceName, var json = JsonConvert.SerializeObject(_serviceEntries);
Address = "localhost", context.Response.Headers.Add("Content-Type", "application/json");
Port = 50881, await context.Response.WriteAsync(json);
ID = Guid.NewGuid().ToString(), }
Tags = new string[0] });
}, })
}; .Build();
this.Given(_ => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName)) _fakeConsulBuilder.Start();
.And(_ => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne)) }
.When(_ => WhenIGetTheServices())
.Then(_ => ThenTheCountIs(1)) public void Dispose()
.And(_ => _receivedToken.ShouldBe(token)) {
.BDDfy(); _fakeConsulBuilder?.Dispose();
} }
}
[Fact] }
public void should_not_return_services_with_invalid_address()
{
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "http://localhost",
Port = 50881,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
var serviceEntryTwo = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "http://localhost",
Port = 50888,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
.When(x => WhenIGetTheServices())
.Then(x => ThenTheCountIs(0))
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress())
.BDDfy();
}
[Fact]
public void should_not_return_services_with_empty_address()
{
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "",
Port = 50881,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
var serviceEntryTwo = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = null,
Port = 50888,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
.When(x => WhenIGetTheServices())
.Then(x => ThenTheCountIs(0))
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForEmptyAddress())
.BDDfy();
}
[Fact]
public void should_not_return_services_with_invalid_port()
{
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "localhost",
Port = -1,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
var serviceEntryTwo = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "localhost",
Port = 0,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
.And(x => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne, serviceEntryTwo))
.When(x => WhenIGetTheServices())
.Then(x => ThenTheCountIs(0))
.And(x => ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts())
.BDDfy();
}
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidAddress()
{
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: http://localhost and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: http://localhost and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
}
private void ThenTheLoggerHasBeenCalledCorrectlyForEmptyAddress()
{
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: and Port: 50881 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: and Port: 50888 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
}
private void ThenTheLoggerHasBeenCalledCorrectlyForInvalidPorts()
{
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: localhost and Port: -1 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
_logger.Verify(
x => x.LogWarning(
"Unable to use service Address: localhost and Port: 0 as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"),
Times.Once);
}
private void ThenTheCountIs(int count)
{
_services.Count.ShouldBe(count);
}
private void WhenIGetTheServices()
{
_services = _provider.Get().GetAwaiter().GetResult();
}
private void GivenTheServicesAreRegisteredWithConsul(params ServiceEntry[] serviceEntries)
{
foreach (var serviceEntry in serviceEntries)
{
_serviceEntries.Add(serviceEntry);
}
}
private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url, string serviceName)
{
_fakeConsulBuilder = new WebHostBuilder()
.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls(url)
.Configure(app =>
{
app.Run(async context =>
{
if (context.Request.Path.Value == $"/v1/health/service/{serviceName}")
{
if (context.Request.Headers.TryGetValue("X-Consul-Token", out var values))
{
_receivedToken = values.First();
}
var json = JsonConvert.SerializeObject(_serviceEntries);
context.Response.Headers.Add("Content-Type", "application/json");
await context.Response.WriteAsync(json);
}
});
})
.Build();
_fakeConsulBuilder.Start();
}
public void Dispose()
{
_fakeConsulBuilder?.Dispose();
}
}
}

View File

@ -6,10 +6,10 @@
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Repository; using Ocelot.Configuration.Repository;
using Provider.Eureka; using Ocelot.Provider.Eureka;
using Responses; using Ocelot.Responses;
using Shouldly; using Shouldly;
using Steeltoe.Common.Discovery; using Steeltoe.Discovery;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit; using Xunit;

View File

@ -5,7 +5,7 @@
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Provider.Eureka; using Provider.Eureka;
using Shouldly; using Shouldly;
using Steeltoe.Common.Discovery; using Steeltoe.Discovery;
using Xunit; using Xunit;
public class EurekaProviderFactoryTests public class EurekaProviderFactoryTests

View File

@ -1,117 +1,118 @@
namespace Ocelot.UnitTests.Eureka namespace Ocelot.UnitTests.Eureka
{ {
using Moq; using Moq;
using Provider.Eureka; using Ocelot.Provider.Eureka;
using Shouldly; using Shouldly;
using Steeltoe.Common.Discovery; using Steeltoe.Common.Discovery;
using System; using Steeltoe.Discovery;
using System.Collections.Generic; using System;
using System.Threading.Tasks; using System.Collections.Generic;
using TestStack.BDDfy; using System.Threading.Tasks;
using Values; using TestStack.BDDfy;
using Xunit; using Ocelot.Values;
using Xunit;
public class EurekaServiceDiscoveryProviderTests
{ public class EurekaServiceDiscoveryProviderTests
private readonly Eureka _provider; {
private readonly Mock<IDiscoveryClient> _client; private readonly Eureka _provider;
private readonly string _serviceId; private readonly Mock<IDiscoveryClient> _client;
private List<IServiceInstance> _instances; private readonly string _serviceId;
private List<Service> _result; private List<IServiceInstance> _instances;
private List<Service> _result;
public EurekaServiceDiscoveryProviderTests()
{ public EurekaServiceDiscoveryProviderTests()
_serviceId = "Laura"; {
_client = new Mock<IDiscoveryClient>(); _serviceId = "Laura";
_provider = new Eureka(_serviceId, _client.Object); _client = new Mock<IDiscoveryClient>();
} _provider = new Eureka(_serviceId, _client.Object);
}
[Fact]
public void should_return_empty_services() [Fact]
{ public void should_return_empty_services()
this.When(_ => WhenIGet()) {
.Then(_ => ThenTheCountIs(0)) this.When(_ => WhenIGet())
.BDDfy(); .Then(_ => ThenTheCountIs(0))
} .BDDfy();
}
[Fact]
public void should_return_service_from_client() [Fact]
{ public void should_return_service_from_client()
var instances = new List<IServiceInstance> {
{ var instances = new List<IServiceInstance>
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>()) {
}; new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
};
this.Given(_ => GivenThe(instances))
.When(_ => WhenIGet()) this.Given(_ => GivenThe(instances))
.Then(_ => ThenTheCountIs(1)) .When(_ => WhenIGet())
.And(_ => ThenTheClientIsCalledCorrectly()) .Then(_ => ThenTheCountIs(1))
.And(_ => ThenTheServiceIsMapped()) .And(_ => ThenTheClientIsCalledCorrectly())
.BDDfy(); .And(_ => ThenTheServiceIsMapped())
} .BDDfy();
}
[Fact]
public void should_return_services_from_client() [Fact]
{ public void should_return_services_from_client()
var instances = new List<IServiceInstance> {
{ var instances = new List<IServiceInstance>
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>()), {
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>()) new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>()),
}; new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
};
this.Given(_ => GivenThe(instances))
.When(_ => WhenIGet()) this.Given(_ => GivenThe(instances))
.Then(_ => ThenTheCountIs(2)) .When(_ => WhenIGet())
.And(_ => ThenTheClientIsCalledCorrectly()) .Then(_ => ThenTheCountIs(2))
.BDDfy(); .And(_ => ThenTheClientIsCalledCorrectly())
} .BDDfy();
}
private void ThenTheServiceIsMapped()
{ private void ThenTheServiceIsMapped()
_result[0].HostAndPort.DownstreamHost.ShouldBe("somehost"); {
_result[0].HostAndPort.DownstreamPort.ShouldBe(801); _result[0].HostAndPort.DownstreamHost.ShouldBe("somehost");
_result[0].Name.ShouldBe(_serviceId); _result[0].HostAndPort.DownstreamPort.ShouldBe(801);
} _result[0].Name.ShouldBe(_serviceId);
}
private void ThenTheCountIs(int expected)
{ private void ThenTheCountIs(int expected)
_result.Count.ShouldBe(expected); {
} _result.Count.ShouldBe(expected);
}
private void ThenTheClientIsCalledCorrectly()
{ private void ThenTheClientIsCalledCorrectly()
_client.Verify(x => x.GetInstances(_serviceId), Times.Once); {
} _client.Verify(x => x.GetInstances(_serviceId), Times.Once);
}
private async Task WhenIGet()
{ private async Task WhenIGet()
_result = await _provider.Get(); {
} _result = await _provider.Get();
}
private void GivenThe(List<IServiceInstance> instances)
{ private void GivenThe(List<IServiceInstance> instances)
_instances = instances; {
_client.Setup(x => x.GetInstances(It.IsAny<string>())).Returns(instances); _instances = instances;
} _client.Setup(x => x.GetInstances(It.IsAny<string>())).Returns(instances);
} }
}
public class EurekaService : IServiceInstance
{ public class EurekaService : IServiceInstance
public EurekaService(string serviceId, string host, int port, bool isSecure, Uri uri, IDictionary<string, string> metadata) {
{ public EurekaService(string serviceId, string host, int port, bool isSecure, Uri uri, IDictionary<string, string> metadata)
ServiceId = serviceId; {
Host = host; ServiceId = serviceId;
Port = port; Host = host;
IsSecure = isSecure; Port = port;
Uri = uri; IsSecure = isSecure;
Metadata = metadata; Uri = uri;
} Metadata = metadata;
}
public string ServiceId { get; }
public string Host { get; } public string ServiceId { get; }
public int Port { get; } public string Host { get; }
public bool IsSecure { get; } public int Port { get; }
public Uri Uri { get; } public bool IsSecure { get; }
public IDictionary<string, string> Metadata { get; } public Uri Uri { get; }
} public IDictionary<string, string> Metadata { get; }
} }
}

View File

@ -1,128 +1,129 @@
namespace Ocelot.UnitTests.Headers namespace Ocelot.UnitTests.Headers
{ {
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Moq; using Microsoft.Extensions.Primitives;
using Ocelot.Configuration.Creator; using Moq;
using Ocelot.Headers; using Ocelot.Configuration.Creator;
using Ocelot.Infrastructure; using Ocelot.Headers;
using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Infrastructure;
using Ocelot.Logging; using Ocelot.Infrastructure.Claims.Parser;
using Responder; using Ocelot.Logging;
using Responses; using Responder;
using Shouldly; using Responses;
using TestStack.BDDfy; using Shouldly;
using Xunit; using TestStack.BDDfy;
using Xunit;
public class AddHeadersToRequestPlainTests
{ public class AddHeadersToRequestPlainTests
private readonly AddHeadersToRequest _addHeadersToRequest; {
private HttpContext _context; private readonly AddHeadersToRequest _addHeadersToRequest;
private AddHeader _addedHeader; private HttpContext _context;
private readonly Mock<IPlaceholders> _placeholders; private AddHeader _addedHeader;
private Mock<IOcelotLoggerFactory> _factory; private readonly Mock<IPlaceholders> _placeholders;
private readonly Mock<IOcelotLogger> _logger; private Mock<IOcelotLoggerFactory> _factory;
private readonly Mock<IOcelotLogger> _logger;
public AddHeadersToRequestPlainTests()
{ public AddHeadersToRequestPlainTests()
_placeholders = new Mock<IPlaceholders>(); {
_factory = new Mock<IOcelotLoggerFactory>(); _placeholders = new Mock<IPlaceholders>();
_logger = new Mock<IOcelotLogger>(); _factory = new Mock<IOcelotLoggerFactory>();
_factory.Setup(x => x.CreateLogger<AddHeadersToRequest>()).Returns(_logger.Object); _logger = new Mock<IOcelotLogger>();
_addHeadersToRequest = new AddHeadersToRequest(Mock.Of<IClaimsParser>(), _placeholders.Object, _factory.Object); _factory.Setup(x => x.CreateLogger<AddHeadersToRequest>()).Returns(_logger.Object);
} _addHeadersToRequest = new AddHeadersToRequest(Mock.Of<IClaimsParser>(), _placeholders.Object, _factory.Object);
}
[Fact]
public void should_log_error_if_cannot_find_placeholder() [Fact]
{ public void should_log_error_if_cannot_find_placeholder()
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new ErrorResponse<string>(new AnyError())); {
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new ErrorResponse<string>(new AnyError()));
this.Given(_ => GivenHttpRequestWithoutHeaders())
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}")) this.Given(_ => GivenHttpRequestWithoutHeaders())
.Then(_ => ThenAnErrorIsLogged("X-Forwarded-For", "{RemoteIdAddress}")) .When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
.BDDfy(); .Then(_ => ThenAnErrorIsLogged("X-Forwarded-For", "{RemoteIdAddress}"))
} .BDDfy();
}
[Fact]
public void should_add_placeholder_to_downstream_request() [Fact]
{ public void should_add_placeholder_to_downstream_request()
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new OkResponse<string>("replaced")); {
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new OkResponse<string>("replaced"));
this.Given(_ => GivenHttpRequestWithoutHeaders())
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}")) this.Given(_ => GivenHttpRequestWithoutHeaders())
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders("replaced")) .When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
.BDDfy(); .Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders("replaced"))
} .BDDfy();
}
[Fact]
public void should_add_plain_text_header_to_downstream_request() [Fact]
{ public void should_add_plain_text_header_to_downstream_request()
this.Given(_ => GivenHttpRequestWithoutHeaders()) {
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue")) this.Given(_ => GivenHttpRequestWithoutHeaders())
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders()) .When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
.BDDfy(); .Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
} .BDDfy();
}
[Fact]
public void should_overwrite_existing_header_with_added_header() [Fact]
{ public void should_overwrite_existing_header_with_added_header()
this.Given(_ => GivenHttpRequestWithHeader("X-Custom-Header", "This should get overwritten")) {
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue")) this.Given(_ => GivenHttpRequestWithHeader("X-Custom-Header", "This should get overwritten"))
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders()) .When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
.BDDfy(); .Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
} .BDDfy();
}
private void ThenAnErrorIsLogged(string key, string value)
{ private void ThenAnErrorIsLogged(string key, string value)
_logger.Verify(x => x.LogWarning($"Unable to add header to response {key}: {value}"), Times.Once); {
} _logger.Verify(x => x.LogWarning($"Unable to add header to response {key}: {value}"), Times.Once);
}
private void GivenHttpRequestWithoutHeaders()
{ private void GivenHttpRequestWithoutHeaders()
_context = new DefaultHttpContext {
{ _context = new DefaultHttpContext
Request = {
{ Request =
Headers = {
{ Headers =
} {
} }
}; }
} };
}
private void GivenHttpRequestWithHeader(string headerKey, string headerValue)
{ private void GivenHttpRequestWithHeader(string headerKey, string headerValue)
_context = new DefaultHttpContext {
{ _context = new DefaultHttpContext
Request = {
{ Request =
Headers = {
{ Headers =
{ headerKey, headerValue } {
} { headerKey, headerValue }
} }
}; }
} };
}
private void WhenAddingHeader(string headerKey, string headerValue)
{ private void WhenAddingHeader(string headerKey, string headerValue)
_addedHeader = new AddHeader(headerKey, headerValue); {
_addHeadersToRequest.SetHeadersOnDownstreamRequest(new[] { _addedHeader }, _context); _addedHeader = new AddHeader(headerKey, headerValue);
} _addHeadersToRequest.SetHeadersOnDownstreamRequest(new[] { _addedHeader }, _context);
}
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders()
{ private void ThenTheHeaderGetsTakenOverToTheRequestHeaders()
var requestHeaders = _context.Request.Headers; {
requestHeaders.ContainsKey(_addedHeader.Key).ShouldBeTrue($"Header {_addedHeader.Key} was expected but not there."); var requestHeaders = _context.Request.Headers;
var value = requestHeaders[_addedHeader.Key]; requestHeaders.ContainsKey(_addedHeader.Key).ShouldBeTrue($"Header {_addedHeader.Key} was expected but not there.");
value.ShouldNotBeNull($"Value of header {_addedHeader.Key} was expected to not be null."); var value = requestHeaders[_addedHeader.Key];
value.ToString().ShouldBe(_addedHeader.Value); value.ShouldNotBe(default(StringValues), $"Value of header {_addedHeader.Key} was expected to not be null.");
} value.ToString().ShouldBe(_addedHeader.Value);
}
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders(string expected)
{ private void ThenTheHeaderGetsTakenOverToTheRequestHeaders(string expected)
var requestHeaders = _context.Request.Headers; {
var value = requestHeaders[_addedHeader.Key]; var requestHeaders = _context.Request.Headers;
value.ToString().ShouldBe(expected); var value = requestHeaders[_addedHeader.Key];
} value.ToString().ShouldBe(expected);
} }
} }
}

View File

@ -1,88 +1,88 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Responses; using Ocelot.Responses;
using Shouldly; using Shouldly;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
namespace Ocelot.UnitTests.Infrastructure namespace Ocelot.UnitTests.Infrastructure
{ {
public class HttpDataRepositoryTests public class HttpDataRepositoryTests
{ {
private readonly HttpContext _httpContext; private readonly HttpContext _httpContext;
private IHttpContextAccessor _httpContextAccessor; private IHttpContextAccessor _httpContextAccessor;
private readonly HttpDataRepository _httpDataRepository; private readonly HttpDataRepository _httpDataRepository;
private object _result; private object _result;
public HttpDataRepositoryTests() public HttpDataRepositoryTests()
{ {
_httpContext = new DefaultHttpContext(); _httpContext = new DefaultHttpContext();
_httpContextAccessor = new HttpContextAccessor { HttpContext = _httpContext }; _httpContextAccessor = new HttpContextAccessor { HttpContext = _httpContext };
_httpDataRepository = new HttpDataRepository(_httpContextAccessor); _httpDataRepository = new HttpDataRepository(_httpContextAccessor);
} }
/* /*
TODO - Additional tests -> Type mistmatch aka Add string, request int TODO - Additional tests -> Type mistmatch aka Add string, request int
TODO - Additional tests -> HttpContent null. This should never happen TODO - Additional tests -> HttpContent null. This should never happen
*/ */
[Fact] [Fact]
public void get_returns_correct_key_from_http_context() public void get_returns_correct_key_from_http_context()
{ {
this.Given(x => x.GivenAHttpContextContaining("key", "string")) this.Given(x => x.GivenAHttpContextContaining("key", "string"))
.When(x => x.GetIsCalledWithKey<string>("key")) .When(x => x.GetIsCalledWithKey<string>("key"))
.Then(x => x.ThenTheResultIsAnOkResponse<string>("string")) .Then(x => x.ThenTheResultIsAnOkResponse<string>("string"))
.BDDfy(); .BDDfy();
} }
[Fact] [Fact]
public void get_returns_error_response_if_the_key_is_not_found() //Therefore does not return null public void get_returns_error_response_if_the_key_is_not_found() //Therefore does not return null
{ {
this.Given(x => x.GivenAHttpContextContaining("key", "string")) this.Given(x => x.GivenAHttpContextContaining("key", "string"))
.When(x => x.GetIsCalledWithKey<string>("keyDoesNotExist")) .When(x => x.GetIsCalledWithKey<string>("keyDoesNotExist"))
.Then(x => x.ThenTheResultIsAnErrorReposnse<string>("string1")) .Then(x => x.ThenTheResultIsAnErrorReposnse<string>("string1"))
.BDDfy(); .BDDfy();
} }
[Fact] [Fact]
public void should_update() public void should_update()
{ {
this.Given(x => x.GivenAHttpContextContaining("key", "string")) this.Given(x => x.GivenAHttpContextContaining("key", "string"))
.And(x => x.UpdateIsCalledWith<string>("key", "new string")) .And(x => x.UpdateIsCalledWith<string>("key", "new string"))
.When(x => x.GetIsCalledWithKey<string>("key")) .When(x => x.GetIsCalledWithKey<string>("key"))
.Then(x => x.ThenTheResultIsAnOkResponse<string>("new string")) .Then(x => x.ThenTheResultIsAnOkResponse<string>("new string"))
.BDDfy(); .BDDfy();
} }
private void UpdateIsCalledWith<T>(string key, string value) private void UpdateIsCalledWith<T>(string key, string value)
{ {
_httpDataRepository.Update(key, value); _httpDataRepository.Update(key, value);
} }
private void GivenAHttpContextContaining(string key, object o) private void GivenAHttpContextContaining(string key, object o)
{ {
_httpContext.Items.Add(key, o); _httpContext.Items.Add(key, o);
} }
private void GetIsCalledWithKey<T>(string key) private void GetIsCalledWithKey<T>(string key)
{ {
_result = _httpDataRepository.Get<T>(key); _result = _httpDataRepository.Get<T>(key);
} }
private void ThenTheResultIsAnErrorReposnse<T>(object resultValue) private void ThenTheResultIsAnErrorReposnse<T>(object resultValue)
{ {
_result.ShouldBeOfType<ErrorResponse<T>>(); _result.ShouldBeOfType<ErrorResponse<T>>();
((ErrorResponse<T>)_result).Data.ShouldBeNull(); ((ErrorResponse<T>)_result).Data.ShouldBe(default(T));
((ErrorResponse<T>)_result).IsError.ShouldBe(true); ((ErrorResponse<T>)_result).IsError.ShouldBe(true);
((ErrorResponse<T>)_result).Errors.ShouldHaveSingleItem() ((ErrorResponse<T>)_result).Errors.ShouldHaveSingleItem()
.ShouldBeOfType<CannotFindDataError>() .ShouldBeOfType<CannotFindDataError>()
.Message.ShouldStartWith("Unable to find data for key: "); .Message.ShouldStartWith("Unable to find data for key: ");
} }
private void ThenTheResultIsAnOkResponse<T>(object resultValue) private void ThenTheResultIsAnOkResponse<T>(object resultValue)
{ {
_result.ShouldBeOfType<OkResponse<T>>(); _result.ShouldBeOfType<OkResponse<T>>();
((OkResponse<T>)_result).Data.ShouldBe(resultValue); ((OkResponse<T>)_result).Data.ShouldBe(resultValue);
} }
} }
} }

View File

@ -1,149 +1,154 @@
using KubeClient; using KubeClient;
using KubeClient.Models; using KubeClient.Models;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Moq; using Moq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Provider.Kubernetes; using Ocelot.Provider.Kubernetes;
using Ocelot.Values; using Ocelot.Values;
using Shouldly; using Shouldly;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
namespace Ocelot.UnitTests.Kubernetes namespace Ocelot.UnitTests.Kubernetes
{ {
public class KubeServiceDiscoveryProviderTests : IDisposable public class KubeServiceDiscoveryProviderTests : IDisposable
{ {
private IWebHost _fakeKubeBuilder; private IWebHost _fakeKubeBuilder;
private readonly KubernetesServiceDiscoveryProvider _provider; private readonly KubernetesServiceDiscoveryProvider _provider;
private EndpointsV1 _endpointEntries; private EndpointsV1 _endpointEntries;
private readonly string _serviceName; private readonly string _serviceName;
private readonly string _namespaces; private readonly string _namespaces;
private readonly int _port; private readonly int _port;
private readonly string _kubeHost; private readonly string _kubeHost;
private readonly string _fakekubeServiceDiscoveryUrl; private readonly string _fakekubeServiceDiscoveryUrl;
private List<Service> _services; private List<Service> _services;
private readonly Mock<IOcelotLoggerFactory> _factory; private readonly Mock<IOcelotLoggerFactory> _factory;
private readonly Mock<IOcelotLogger> _logger; private readonly Mock<IOcelotLogger> _logger;
private string _receivedToken; private string _receivedToken;
private readonly IKubeApiClient _clientFactory; private readonly IKubeApiClient _clientFactory;
public KubeServiceDiscoveryProviderTests() public KubeServiceDiscoveryProviderTests()
{ {
_serviceName = "test"; _serviceName = "test";
_namespaces = "dev"; _namespaces = "dev";
_port = 86; _port = 86;
_kubeHost = "localhost"; _kubeHost = "localhost";
_fakekubeServiceDiscoveryUrl = $"http://{_kubeHost}:{_port}"; _fakekubeServiceDiscoveryUrl = $"http://{_kubeHost}:{_port}";
_endpointEntries = new EndpointsV1(); _endpointEntries = new EndpointsV1();
_factory = new Mock<IOcelotLoggerFactory>(); _factory = new Mock<IOcelotLoggerFactory>();
var option = new KubeClientOptions var option = new KubeClientOptions
{ {
ApiEndPoint = new Uri(_fakekubeServiceDiscoveryUrl), ApiEndPoint = new Uri(_fakekubeServiceDiscoveryUrl),
AccessToken = "txpc696iUhbVoudg164r93CxDTrKRVWG", AccessToken = "txpc696iUhbVoudg164r93CxDTrKRVWG",
AuthStrategy = KubeClient.KubeAuthStrategy.BearerToken, AuthStrategy = KubeClient.KubeAuthStrategy.BearerToken,
AllowInsecure = true, AllowInsecure = true,
}; };
_clientFactory = KubeApiClient.Create(option); _clientFactory = KubeApiClient.Create(option);
_logger = new Mock<IOcelotLogger>(); _logger = new Mock<IOcelotLogger>();
_factory.Setup(x => x.CreateLogger<KubernetesServiceDiscoveryProvider>()).Returns(_logger.Object); _factory.Setup(x => x.CreateLogger<KubernetesServiceDiscoveryProvider>()).Returns(_logger.Object);
var config = new KubeRegistryConfiguration() var config = new KubeRegistryConfiguration()
{ {
KeyOfServiceInK8s = _serviceName, KeyOfServiceInK8s = _serviceName,
KubeNamespace = _namespaces, KubeNamespace = _namespaces,
}; };
_provider = new KubernetesServiceDiscoveryProvider(config, _factory.Object, _clientFactory); _provider = new KubernetesServiceDiscoveryProvider(config, _factory.Object, _clientFactory);
}
[Fact]
public void should_return_service_from_k8s()
{
var token = "Bearer txpc696iUhbVoudg164r93CxDTrKRVWG";
var endPointEntryOne = new EndpointsV1
{
Kind = "endpoint",
ApiVersion = "1.0",
Metadata = new ObjectMetaV1()
{
Namespace = "dev",
},
};
var endpointSubsetV1 = new EndpointSubsetV1();
endpointSubsetV1.Addresses.Add(new EndpointAddressV1()
{
Ip = "127.0.0.1",
Hostname = "localhost",
});
endpointSubsetV1.Ports.Add(new EndpointPortV1()
{
Port = 80,
});
endPointEntryOne.Subsets.Add(endpointSubsetV1);
this.Given(x => GivenThereIsAFakeKubeServiceDiscoveryProvider(_fakekubeServiceDiscoveryUrl, _serviceName, _namespaces))
.And(x => GivenTheServicesAreRegisteredWithKube(endPointEntryOne))
.When(x => WhenIGetTheServices())
.Then(x => ThenTheCountIs(1))
.And(_ => ThenTheTokenIs(token))
.BDDfy();
} }
[Fact] private void ThenTheTokenIs(string token)
public void should_return_service_from_k8s()
{ {
var token = "Bearer txpc696iUhbVoudg164r93CxDTrKRVWG"; _receivedToken.ShouldBe(token);
var endPointEntryOne = new EndpointsV1 }
{
Kind = "endpoint", private void ThenTheCountIs(int count)
ApiVersion = "1.0", {
Metadata = new ObjectMetaV1() _services.Count.ShouldBe(count);
{ }
Namespace = "dev",
}, private void WhenIGetTheServices()
}; {
var endpointSubsetV1 = new EndpointSubsetV1(); _services = _provider.Get().GetAwaiter().GetResult();
endpointSubsetV1.Addresses.Add(new EndpointAddressV1() }
{
Ip = "127.0.0.1", private void GivenTheServicesAreRegisteredWithKube(EndpointsV1 endpointEntries)
Hostname = "localhost", {
}); _endpointEntries = endpointEntries;
endpointSubsetV1.Ports.Add(new EndpointPortV1() }
{
Port = 80, private void GivenThereIsAFakeKubeServiceDiscoveryProvider(string url, string serviceName, string namespaces)
}); {
endPointEntryOne.Subsets.Add(endpointSubsetV1); _fakeKubeBuilder = new WebHostBuilder()
.UseUrls(url)
this.Given(x => GivenThereIsAFakeKubeServiceDiscoveryProvider(_fakekubeServiceDiscoveryUrl, _serviceName, _namespaces)) .UseKestrel()
.And(x => GivenTheServicesAreRegisteredWithKube(endPointEntryOne)) .UseContentRoot(Directory.GetCurrentDirectory())
.When(x => WhenIGetTheServices()) .UseIISIntegration()
.Then(x => ThenTheCountIs(1)) .UseUrls(url)
.And(_ => _receivedToken.ShouldBe(token)) .Configure(app =>
.BDDfy(); {
} app.Run(async context =>
{
private void ThenTheCountIs(int count) if (context.Request.Path.Value == $"/api/v1/namespaces/{namespaces}/endpoints/{serviceName}")
{ {
_services.Count.ShouldBe(count); if (context.Request.Headers.TryGetValue("Authorization", out var values))
} {
_receivedToken = values.First();
private void WhenIGetTheServices() }
{
_services = _provider.Get().GetAwaiter().GetResult(); var json = JsonConvert.SerializeObject(_endpointEntries);
} context.Response.Headers.Add("Content-Type", "application/json");
await context.Response.WriteAsync(json);
private void GivenTheServicesAreRegisteredWithKube(EndpointsV1 endpointEntries) }
{ });
_endpointEntries = endpointEntries; })
} .Build();
private void GivenThereIsAFakeKubeServiceDiscoveryProvider(string url, string serviceName, string namespaces) _fakeKubeBuilder.Start();
{ }
_fakeKubeBuilder = new WebHostBuilder()
.UseUrls(url) public void Dispose()
.UseKestrel() {
.UseContentRoot(Directory.GetCurrentDirectory()) _fakeKubeBuilder?.Dispose();
.UseIISIntegration() }
.UseUrls(url) }
.Configure(app => }
{
app.Run(async context =>
{
if (context.Request.Path.Value == $"/api/v1/namespaces/{namespaces}/endpoints/{serviceName}")
{
if (context.Request.Headers.TryGetValue("Authorization", out var values))
{
_receivedToken = values.First();
}
var json = JsonConvert.SerializeObject(_endpointEntries);
context.Response.Headers.Add("Content-Type", "application/json");
await context.Response.WriteAsync(json);
}
});
})
.Build();
_fakeKubeBuilder.Start();
}
public void Dispose()
{
_fakeKubeBuilder?.Dispose();
}
}
}

View File

@ -54,7 +54,7 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164"> <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
@ -67,13 +67,13 @@
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
<PackageReference Include="Moq" Version="4.15.2" /> <PackageReference Include="Moq" Version="4.15.2" />
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" /> <PackageReference Include="Shouldly" Version="4.0.1" />
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" /> <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" /> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="IdentityServer4" Version="3.1.1" /> <PackageReference Include="IdentityServer4" Version="3.1.1" />
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.4.2" /> <PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.1" />
<PackageReference Include="Consul" Version="1.6.1.1" /> <PackageReference Include="Consul" Version="1.6.1.1" />
<PackageReference Include="CacheManager.Core" Version="2.0.0-beta-1629" /> <PackageReference Include="CacheManager.Core" Version="2.0.0-beta-1629" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="2.0.0-beta-1629" /> <PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="2.0.0-beta-1629" />

View File

@ -452,7 +452,7 @@
foreach (var header in _mappedRequest.Data.Headers) foreach (var header in _mappedRequest.Data.Headers)
{ {
var inputHeader = _inputHeaders.First(h => h.Key == header.Key); var inputHeader = _inputHeaders.First(h => h.Key == header.Key);
inputHeader.ShouldNotBeNull(); inputHeader.ShouldNotBe(default(KeyValuePair<string, StringValues>));
inputHeader.Value.Count().ShouldBe(header.Value.Count()); inputHeader.Value.Count().ShouldBe(header.Value.Count());
foreach (var inputHeaderValue in inputHeader.Value) foreach (var inputHeaderValue in inputHeader.Value)
{ {