public void EmptyTransforms_AddsDefaults() { var transformBuilder = CreateTransformBuilder(); var errorReporter = new TestConfigErrorReporter(); var transforms = new List <IDictionary <string, string> >(); var valid = transformBuilder.Validate(transforms, "routeId", errorReporter); Assert.True(valid); Assert.Empty(errorReporter.Errors); var results = transformBuilder.Build(transforms); Assert.NotNull(results); Assert.Null(results.CopyRequestHeaders); Assert.Empty(results.ResponseHeaderTransforms); Assert.Empty(results.ResponseTrailerTransforms); Assert.Empty(results.RequestTransforms); Assert.Equal(5, results.RequestHeaderTransforms.Count); Assert.IsType <RequestHeaderValueTransform>(results.RequestHeaderTransforms[HeaderNames.Host]); Assert.IsType <RequestHeaderXForwardedForTransform>(results.RequestHeaderTransforms[ForwardedHeadersDefaults.XForwardedForHeaderName]); Assert.IsType <RequestHeaderXForwardedHostTransform>(results.RequestHeaderTransforms[ForwardedHeadersDefaults.XForwardedHostHeaderName]); Assert.IsType <RequestHeaderXForwardedPathBaseTransform>(results.RequestHeaderTransforms["X-Forwarded-PathBase"]); Assert.IsType <RequestHeaderXForwardedProtoTransform>(results.RequestHeaderTransforms[ForwardedHeadersDefaults.XForwardedProtoHeaderName]); }
public void DefaultsCanBeDisabled() { var transformBuilder = CreateTransformBuilder(); var errorReporter = new TestConfigErrorReporter(); var transforms = new List <IDictionary <string, string> >() { new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { "RequestHeaderOriginalHost", "true" } }, new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { "X-Forwarded", "" } }, }; var valid = transformBuilder.Validate(transforms, "routeId", errorReporter); Assert.True(valid); Assert.Empty(errorReporter.Errors); var results = transformBuilder.Build(transforms); Assert.NotNull(results); Assert.Null(results.CopyRequestHeaders); Assert.Empty(results.ResponseHeaderTransforms); Assert.Empty(results.ResponseTrailerTransforms); Assert.Empty(results.RequestTransforms); Assert.Empty(results.RequestHeaderTransforms); }
public async Task BuildConfigAsync_ConfigFilterRouteActionThrows_SkipsRoute() { var errorReporter = new TestConfigErrorReporter(); var route1 = new ProxyRoute { RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, BackendId = "backend1" }; var route2 = new ProxyRoute { RouteId = "route2", Match = { Host = "example2.com" }, Priority = 1, BackendId = "backend2" }; var configBuilder = CreateConfigBuilder(new TestBackendsRepo(), new TestRoutesRepo(new[] { route1, route2 }), proxyBuilder => { proxyBuilder.AddProxyConfigFilter <BackendAndRouteThrows>(); proxyBuilder.AddProxyConfigFilter <BackendAndRouteThrows>(); }); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert Assert.True(result.IsSuccess); Assert.NotNull(result.Value); Assert.Empty(result.Value.Backends); Assert.Empty(result.Value.Routes); Assert.Equal(2, errorReporter.Errors.Count); Assert.IsType <NotFiniteNumberException>(errorReporter.Errors.First().Exception); Assert.IsType <NotFiniteNumberException>(errorReporter.Errors.Skip(1).First().Exception); }
public async Task BuildConfigAsync_ConfigFilterConfiguresCluster_Works() { var errorReporter = new TestConfigErrorReporter(); var configBuilder = CreateConfigBuilder(CreateOneCluster(), new TestRoutesRepo(), proxyBuilder => { proxyBuilder.AddProxyConfigFilter <ClusterAndRouteFilter>(); }); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); Assert.Empty(errorReporter.Errors); Assert.NotNull(result); Assert.Single(result.Clusters); var cluster = result.Clusters["cluster1"]; Assert.NotNull(cluster); Assert.True(cluster.HealthCheckOptions.Enabled); Assert.Equal(TimeSpan.FromSeconds(12), cluster.HealthCheckOptions.Interval); Assert.Single(cluster.Destinations); var destination = cluster.Destinations["d1"]; Assert.NotNull(destination); Assert.Equal(TestAddress, destination.Address); }
public async Task BuildConfigAsync_ConfigFilterConfiguresBackend_Works() { var errorReporter = new TestConfigErrorReporter(); var configBuilder = CreateConfigBuilder(CreateOneBackend(), new TestRoutesRepo(), proxyBuilder => { proxyBuilder.AddProxyConfigFilter <BackendAndRouteFilter>(); }); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); Assert.True(result.IsSuccess); Assert.Empty(errorReporter.Errors); Assert.NotNull(result.Value); Assert.Single(result.Value.Backends); var backend = result.Value.Backends["backend1"]; Assert.NotNull(backend); Assert.True(backend.HealthCheckOptions.Enabled); Assert.Equal(TimeSpan.FromSeconds(12), backend.HealthCheckOptions.Interval); Assert.Single(backend.Endpoints); var endpoint = backend.Endpoints["ep1"]; Assert.NotNull(endpoint); Assert.Equal(TestAddress, endpoint.Address); }
public async Task BuildConfigAsync_RouteValidationError_SkipsRoute() { // Arrange var errorReporter = new TestConfigErrorReporter(); Mock <IBackendsRepo>() .Setup(r => r.GetBackendsAsync(It.IsAny <CancellationToken>())) .ReturnsAsync(new Dictionary <string, Backend>()); var route1 = new ProxyRoute { RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, BackendId = "backend1" }; Mock <IRoutesRepo>() .Setup(r => r.GetRoutesAsync(It.IsAny <CancellationToken>())) .ReturnsAsync(new[] { route1 }); var parsedRoute1 = new ParsedRoute(); Mock <IRouteValidator>() .Setup(r => r.ValidateRoute(parsedRoute1, errorReporter)) .Returns(false); // Act var configManager = Create <DynamicConfigBuilder>(); var result = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert result.IsSuccess.Should().BeTrue(); result.Value.Should().NotBeNull(); result.Value.Backends.Should().BeEmpty(); result.Value.Routes.Should().BeEmpty(); }
public void UnknownTransforms_Error() { var transformBuilder = CreateTransformBuilder(); var errorReporter = new TestConfigErrorReporter(); var transforms = new List <IDictionary <string, string> >() { new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) // Unrecognized transform { { "string1", "value1" }, { "string2", "value2" } }, new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) // Unrecognized transform { { "string3", "value3" }, { "string4", "value4" } }, }; var valid = transformBuilder.Validate(transforms, "routeId", errorReporter); Assert.False(valid); // All errors reported Assert.Equal(2, errorReporter.Errors.Count); Assert.Equal("Unknown transform: string1;string2", errorReporter.Errors.First().Message); Assert.Equal("Unknown transform: string3;string4", errorReporter.Errors.Skip(1).First().Message); var nie = Assert.Throws <NotSupportedException>(() => transformBuilder.Build(transforms)); // First error reported Assert.Equal("string1;string2", nie.Message); }
public async Task BuildConfigAsync_ValidRoute_Works() { // Arrange var errorReporter = new TestConfigErrorReporter(); Mock <IBackendsRepo>() .Setup(r => r.GetBackendsAsync(It.IsAny <CancellationToken>())) .ReturnsAsync(new Dictionary <string, Backend>()); var route1 = new ProxyRoute { RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, BackendId = "backend1" }; Mock <IRoutesRepo>() .Setup(r => r.GetRoutesAsync(It.IsAny <CancellationToken>())) .ReturnsAsync(new[] { route1 }); Mock <IRouteValidator>() .Setup(r => r.ValidateRoute(It.IsAny <ParsedRoute>(), errorReporter)) .Returns(true); // Act var configManager = Create <DynamicConfigBuilder>(); var result = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert Assert.True(result.IsSuccess); Assert.Empty(errorReporter.Errors); Assert.NotNull(result.Value); Assert.Empty(result.Value.Backends); Assert.Single(result.Value.Routes); Assert.Same(route1.RouteId, result.Value.Routes[0].RouteId); }
private (bool IsSuccess, TestConfigErrorReporter ErrorReporter) RunScenario(ParsedRoute parsedRoute) { var errorReporter = new TestConfigErrorReporter(); var validator = Create <RouteValidator>(); var isSuccess = validator.ValidateRoute(parsedRoute, errorReporter); return(isSuccess, errorReporter); }
private (bool IsSuccess, TestConfigErrorReporter ErrorReporter) RunScenario(ParsedRoute parsedRoute) { var errorReporter = new TestConfigErrorReporter(); Mock <ITransformBuilder>().Setup(builder => builder.Validate(It.IsAny <IList <IDictionary <string, string> > >(), It.IsAny <string>(), It.IsAny <IConfigErrorReporter>())).Returns(true); var validator = Create <RouteValidator>(); var isSuccess = validator.ValidateRoute(parsedRoute, errorReporter); return(isSuccess, errorReporter); }
public async Task BuildConfigAsync_EmptyInput_Works() { var errorReporter = new TestConfigErrorReporter(); var configBuilder = CreateConfigBuilder(new TestClustersRepo(new Dictionary <string, Cluster>()), new TestRoutesRepo(new List <ProxyRoute>())); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); Assert.Empty(errorReporter.Errors); Assert.NotNull(result); Assert.Empty(result.Clusters); Assert.Empty(result.Routes); }
public async Task BuildConfigAsync_NullInput_Works() { var errorReporter = new TestConfigErrorReporter(); var configBuilder = CreateConfigBuilder(new TestBackendsRepo(), new TestRoutesRepo()); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); Assert.True(result.IsSuccess); Assert.Empty(errorReporter.Errors); Assert.NotNull(result.Value); Assert.Empty(result.Value.Backends); Assert.Empty(result.Value.Routes); }
public async Task BuildConfigAsync_RouteValidationError_SkipsRoute() { var errorReporter = new TestConfigErrorReporter(); var route1 = new ProxyRoute { RouteId = "route1", Match = { Host = "invalid host name" }, Priority = 1, ClusterId = "cluster1" }; var configBuilder = CreateConfigBuilder(new TestClustersRepo(), new TestRoutesRepo(new[] { route1 })); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); Assert.NotNull(result); Assert.Empty(result.Clusters); Assert.Empty(result.Routes); }
public async Task BuildConfigAsync_NullInput_Works() { // Arrange var errorReporter = new TestConfigErrorReporter(); // Act var configManager = Create <DynamicConfigBuilder>(); var result = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert Assert.True(result.IsSuccess); Assert.Empty(errorReporter.Errors); Assert.NotNull(result.Value); Assert.Empty(result.Value.Backends); Assert.Empty(result.Value.Routes); }
public async Task BuildConfigAsync_ValidRoute_Works() { var errorReporter = new TestConfigErrorReporter(); var route1 = new ProxyRoute { RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, ClusterId = "cluster1" }; var configBuilder = CreateConfigBuilder(new TestClustersRepo(), new TestRoutesRepo(new[] { route1 })); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); Assert.Empty(errorReporter.Errors); Assert.NotNull(result); Assert.Empty(result.Clusters); Assert.Single(result.Routes); Assert.Same(route1.RouteId, result.Routes[0].RouteId); }
public async Task BuildConfigAsync_NullInput_Works() { // Arrange var errorReporter = new TestConfigErrorReporter(); // Act var configManager = Create <DynamicConfigBuilder>(); var result = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert result.IsSuccess.Should().BeTrue(); errorReporter.Errors.Should().BeEmpty(); result.Value.Should().NotBeNull(); result.Value.Backends.Should().BeEmpty(); result.Value.Routes.Should().BeEmpty(); }
public void Rejects_MissingRouteId(string routeId) { // Arrange var errorReporter = new TestConfigErrorReporter(); var parsedRoute = new ParsedRoute { RouteId = routeId }; var validator = Create <RouteValidator>(); // Act var isSuccess = validator.ValidateRoute(parsedRoute, errorReporter); // Assert Assert.False(isSuccess); Assert.Contains(errorReporter.Errors, err => err.ErrorCode == ConfigErrors.ParsedRouteMissingId); }
public async Task BuildConfigAsync_OneBackend_Works() { // Arrange const string TestAddress = "https://localhost:123/"; var errorReporter = new TestConfigErrorReporter(); Mock <IBackendsRepo>() .Setup(r => r.GetBackendsAsync(It.IsAny <CancellationToken>())) .ReturnsAsync(new Dictionary <string, Backend> { { "backend1", new Backend { Endpoints = { { "ep1", new BackendEndpoint { Address = TestAddress } } } } } }); Mock <IRoutesRepo>() .Setup(r => r.GetRoutesAsync(It.IsAny <CancellationToken>())) .ReturnsAsync(new List <ProxyRoute>()); // Act var configManager = Create <DynamicConfigBuilder>(); var result = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert result.IsSuccess.Should().BeTrue(); errorReporter.Errors.Should().BeEmpty(); result.Value.Should().NotBeNull(); result.Value.Backends.Should().HaveCount(1); var backend = result.Value.Backends["backend1"]; backend.Should().NotBeNull(); backend.Endpoints.Should().HaveCount(1); var endpoint = backend.Endpoints["ep1"]; endpoint.Should().NotBeNull(); endpoint.Address.Should().Be(TestAddress); }
public async Task BuildConfigAsync_ConfigFilterClusterActionThrows_ClusterSkipped() { var errorReporter = new TestConfigErrorReporter(); var configBuilder = CreateConfigBuilder(CreateOneCluster(), new TestRoutesRepo(), proxyBuilder => { proxyBuilder.AddProxyConfigFilter <ClusterAndRouteThrows>(); proxyBuilder.AddProxyConfigFilter <ClusterAndRouteThrows>(); }); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert Assert.NotNull(result); Assert.Empty(result.Clusters); Assert.NotEmpty(errorReporter.Errors); Assert.IsType <NotFiniteNumberException>(errorReporter.Errors.Single().Exception); }
public async Task BuildConfigAsync_OneBackend_Works() { var errorReporter = new TestConfigErrorReporter(); var configBuilder = CreateConfigBuilder(CreateOneBackend(), new TestRoutesRepo()); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert Assert.True(result.IsSuccess); Assert.Empty(errorReporter.Errors); Assert.NotNull(result.Value); Assert.Single(result.Value.Backends); var backend = result.Value.Backends["backend1"]; Assert.NotNull(backend); Assert.Single(backend.Endpoints); var endpoint = backend.Endpoints["ep1"]; Assert.NotNull(endpoint); Assert.Equal(TestAddress, endpoint.Address); }
public async Task BuildConfigAsync_OneCluster_Works() { var errorReporter = new TestConfigErrorReporter(); var configBuilder = CreateConfigBuilder(CreateOneCluster(), new TestRoutesRepo()); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert Assert.Empty(errorReporter.Errors); Assert.NotNull(result); Assert.Single(result.Clusters); var cluster = result.Clusters["cluster1"]; Assert.NotNull(cluster); Assert.Equal("cluster1", cluster.Id); Assert.Single(cluster.Destinations); var destination = cluster.Destinations["d1"]; Assert.NotNull(destination); Assert.Equal(TestAddress, destination.Address); }
public void CopyRequestHeader(bool copyRequestHeaders) { var transformBuilder = CreateTransformBuilder(); var errorReporter = new TestConfigErrorReporter(); var transforms = new List <IDictionary <string, string> >() { new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { "RequestHeadersCopy", copyRequestHeaders.ToString() } } }; var valid = transformBuilder.Validate(transforms, "routeId", errorReporter); Assert.True(valid); Assert.Empty(errorReporter.Errors); var results = transformBuilder.Build(transforms); Assert.NotNull(results); Assert.Equal(copyRequestHeaders, results.CopyRequestHeaders); }
public async Task BuildConfigAsync_ConfigFilterRouteActions_Works() { var errorReporter = new TestConfigErrorReporter(); var route1 = new ProxyRoute { RouteId = "route1", Match = { Host = "example.com" }, Priority = 1, BackendId = "backend1" }; var configBuilder = CreateConfigBuilder(new TestBackendsRepo(), new TestRoutesRepo(new[] { route1 }), proxyBuilder => { proxyBuilder.AddProxyConfigFilter <BackendAndRouteFilter>(); }); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); Assert.True(result.IsSuccess); Assert.Empty(errorReporter.Errors); Assert.NotNull(result.Value); Assert.Empty(result.Value.Backends); Assert.Single(result.Value.Routes); Assert.Same(route1.RouteId, result.Value.Routes[0].RouteId); Assert.Equal(12, route1.Priority); }
public void EmptyTransform_Error() { var transformBuilder = CreateTransformBuilder(); var errorReporter = new TestConfigErrorReporter(); var transforms = new List <IDictionary <string, string> >() { new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase), // Empty }; var valid = transformBuilder.Validate(transforms, "routeId", errorReporter); Assert.False(valid); Assert.Single(errorReporter.Errors); var error = errorReporter.Errors.First(); Assert.Equal("routeId", error.ElementId); Assert.Equal("Unknown transform: ", error.Message); var nie = Assert.Throws <NotSupportedException>(() => transformBuilder.Build(transforms)); Assert.Equal("", nie.Message); }
public async Task BuildConfigAsync_ConfigFilterRouteActions_CanFixBrokenRoute() { var errorReporter = new TestConfigErrorReporter(); var route1 = new ProxyRoute { RouteId = "route1", Match = { Host = "invalid host name" }, Priority = 1, ClusterId = "cluster1" }; var configBuilder = CreateConfigBuilder(new TestClustersRepo(), new TestRoutesRepo(new[] { route1 }), proxyBuilder => { proxyBuilder.AddProxyConfigFilter <FixRouteHostFilter>(); }); var result = await configBuilder.BuildConfigAsync(errorReporter, CancellationToken.None); Assert.Empty(errorReporter.Errors); Assert.NotNull(result); Assert.Empty(result.Clusters); Assert.Single(result.Routes); var builtRoute = result.Routes[0]; Assert.Same(route1.RouteId, builtRoute.RouteId); Assert.Equal("example.com", builtRoute.Host); }
public void RequestHeader(bool append, string value) { var transformBuilder = CreateTransformBuilder(); var errorReporter = new TestConfigErrorReporter(); var transforms = new List <IDictionary <string, string> >() { new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { "RequestHeader", "HeaderName" }, { append ? "Append" : "Set", value } } }; var valid = transformBuilder.Validate(transforms, "routeId", errorReporter); Assert.True(valid); Assert.Empty(errorReporter.Errors); var results = transformBuilder.Build(transforms); Assert.IsType <RequestHeaderValueTransform>(results.RequestHeaderTransforms["heaDerName"]); // TODO: How to check Append/Set and the value? }
public async Task BuildConfigAsync_EmptyInput_Works() { // Arrange var errorReporter = new TestConfigErrorReporter(); Mock <IBackendsRepo>() .Setup(r => r.GetBackendsAsync(It.IsAny <CancellationToken>())) .ReturnsAsync(new Dictionary <string, Backend>()); Mock <IRoutesRepo>() .Setup(r => r.GetRoutesAsync(It.IsAny <CancellationToken>())) .ReturnsAsync(new List <ProxyRoute>()); // Act var configManager = Create <DynamicConfigBuilder>(); var result = await configManager.BuildConfigAsync(errorReporter, CancellationToken.None); // Assert result.IsSuccess.Should().BeTrue(); errorReporter.Errors.Should().BeEmpty(); result.Value.Should().NotBeNull(); result.Value.Backends.Should().BeEmpty(); result.Value.Routes.Should().BeEmpty(); }
public async Task ApplyConfigurationsAsync_OneClusterOneDestinationOneRoute_Works() { // Arrange const string TestAddress = "https://localhost:123/"; var cluster = new Cluster { Destinations = { { "d1", new Destination { Address = TestAddress } } } }; var route = new ParsedRoute { RouteId = "route1", ClusterId = "cluster1", }; var dynamicConfigRoot = new DynamicConfigRoot { Clusters = new Dictionary <string, Cluster> { { "cluster1", cluster } }, Routes = new[] { route }, }; Mock <IDynamicConfigBuilder>() .Setup(d => d.BuildConfigAsync(It.IsAny <IConfigErrorReporter>(), It.IsAny <CancellationToken>())) .ReturnsAsync(dynamicConfigRoot); var errorReporter = new TestConfigErrorReporter(); var proxyManager = Create <ReverseProxyConfigManager>(); // Act await proxyManager.ApplyConfigurationsAsync(errorReporter, CancellationToken.None); // Assert var actualClusters = _clusterManager.GetItems(); Assert.Single(actualClusters); Assert.Equal("cluster1", actualClusters[0].ClusterId); Assert.NotNull(actualClusters[0].DestinationManager); Assert.NotNull(actualClusters[0].Config.Value); var actualDestinations = actualClusters[0].DestinationManager.GetItems(); Assert.Single(actualDestinations); Assert.Equal("d1", actualDestinations[0].DestinationId); Assert.NotNull(actualDestinations[0].Config.Value); Assert.Equal(TestAddress, actualDestinations[0].Config.Value.Address); var actualRoutes = _routeManager.GetItems(); Assert.Single(actualRoutes); Assert.Equal("route1", actualRoutes[0].RouteId); Assert.NotNull(actualRoutes[0].Config.Value); Assert.Same(actualClusters[0], actualRoutes[0].Config.Value.Cluster); }
public async Task ApplyConfigurationsAsync_OneBackendOneEndpointOneRoute_Works() { // Arrange const string TestAddress = "https://localhost:123/"; var backend = new Backend { Endpoints = { { "ep1", new BackendEndpoint { Address = TestAddress } } } }; var route = new ParsedRoute { RouteId = "route1", BackendId = "backend1", }; var dynamicConfigRoot = new DynamicConfigRoot { Backends = new Dictionary <string, Backend> { { "backend1", backend } }, Routes = new[] { route }, }; Mock <IDynamicConfigBuilder>() .Setup(d => d.BuildConfigAsync(It.IsAny <IConfigErrorReporter>(), It.IsAny <CancellationToken>())) .ReturnsAsync(Result.Success(dynamicConfigRoot)); var errorReporter = new TestConfigErrorReporter(); var proxyManager = Create <ReverseProxyConfigManager>(); // Act var result = await proxyManager.ApplyConfigurationsAsync(errorReporter, CancellationToken.None); // Assert Assert.True(result); var actualBackends = _backendManager.GetItems(); Assert.Single(actualBackends); Assert.Equal("backend1", actualBackends[0].BackendId); Assert.NotNull(actualBackends[0].EndpointManager); Assert.NotNull(actualBackends[0].Config.Value); var actualEndpoints = actualBackends[0].EndpointManager.GetItems(); Assert.Single(actualEndpoints); Assert.Equal("ep1", actualEndpoints[0].EndpointId); Assert.NotNull(actualEndpoints[0].Config.Value); Assert.Equal(TestAddress, actualEndpoints[0].Config.Value.Address); var actualRoutes = _routeManager.GetItems(); Assert.Single(actualRoutes); Assert.Equal("route1", actualRoutes[0].RouteId); Assert.NotNull(actualRoutes[0].Config.Value); Assert.Same(actualBackends[0], actualRoutes[0].Config.Value.BackendOrNull); }