diff --git a/src/Hosting/TestHost/ref/Microsoft.AspNetCore.TestHost.netcoreapp3.0.cs b/src/Hosting/TestHost/ref/Microsoft.AspNetCore.TestHost.netcoreapp3.0.cs index e851c00d4d..3a11a01b93 100644 --- a/src/Hosting/TestHost/ref/Microsoft.AspNetCore.TestHost.netcoreapp3.0.cs +++ b/src/Hosting/TestHost/ref/Microsoft.AspNetCore.TestHost.netcoreapp3.0.cs @@ -17,6 +17,7 @@ namespace Microsoft.AspNetCore.TestHost public partial class RequestBuilder { public RequestBuilder(Microsoft.AspNetCore.TestHost.TestServer server, string path) { } + public Microsoft.AspNetCore.TestHost.TestServer TestServer { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } public Microsoft.AspNetCore.TestHost.RequestBuilder AddHeader(string name, string value) { throw null; } public Microsoft.AspNetCore.TestHost.RequestBuilder And(System.Action configure) { throw null; } public System.Threading.Tasks.Task GetAsync() { throw null; } @@ -25,15 +26,16 @@ namespace Microsoft.AspNetCore.TestHost } public partial class TestServer : Microsoft.AspNetCore.Hosting.Server.IServer, System.IDisposable { - public TestServer() { } public TestServer(Microsoft.AspNetCore.Hosting.IWebHostBuilder builder) { } public TestServer(Microsoft.AspNetCore.Hosting.IWebHostBuilder builder, Microsoft.AspNetCore.Http.Features.IFeatureCollection featureCollection) { } - public TestServer(Microsoft.AspNetCore.Http.Features.IFeatureCollection featureCollection) { } + public TestServer(System.IServiceProvider services) { } + public TestServer(System.IServiceProvider services, Microsoft.AspNetCore.Http.Features.IFeatureCollection featureCollection) { } public bool AllowSynchronousIO { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public System.Uri BaseAddress { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public Microsoft.AspNetCore.Http.Features.IFeatureCollection Features { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } public Microsoft.AspNetCore.Hosting.IWebHost Host { get { throw null; } } public bool PreserveExecutionContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public System.IServiceProvider Services { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } public System.Net.Http.HttpClient CreateClient() { throw null; } public System.Net.Http.HttpMessageHandler CreateHandler() { throw null; } public Microsoft.AspNetCore.TestHost.RequestBuilder CreateRequest(string path) { throw null; } diff --git a/src/Hosting/TestHost/src/RequestBuilder.cs b/src/Hosting/TestHost/src/RequestBuilder.cs index c770ec75ba..644257992e 100644 --- a/src/Hosting/TestHost/src/RequestBuilder.cs +++ b/src/Hosting/TestHost/src/RequestBuilder.cs @@ -13,7 +13,6 @@ namespace Microsoft.AspNetCore.TestHost /// public class RequestBuilder { - private readonly TestServer _server; private readonly HttpRequestMessage _req; /// @@ -23,15 +22,15 @@ namespace Microsoft.AspNetCore.TestHost /// public RequestBuilder(TestServer server, string path) { - if (server == null) - { - throw new ArgumentNullException(nameof(server)); - } - - _server = server; + TestServer = server ?? throw new ArgumentNullException(nameof(server)); _req = new HttpRequestMessage(HttpMethod.Get, path); } + /// + /// Gets the instance for which the request is being built. + /// + public TestServer TestServer { get; } + /// /// Configure any HttpRequestMessage properties. /// @@ -79,7 +78,7 @@ namespace Microsoft.AspNetCore.TestHost public Task SendAsync(string method) { _req.Method = new HttpMethod(method); - return _server.CreateClient().SendAsync(_req); + return TestServer.CreateClient().SendAsync(_req); } /// @@ -89,7 +88,7 @@ namespace Microsoft.AspNetCore.TestHost public Task GetAsync() { _req.Method = HttpMethod.Get; - return _server.CreateClient().SendAsync(_req); + return TestServer.CreateClient().SendAsync(_req); } /// @@ -99,7 +98,7 @@ namespace Microsoft.AspNetCore.TestHost public Task PostAsync() { _req.Method = HttpMethod.Post; - return _server.CreateClient().SendAsync(_req); + return TestServer.CreateClient().SendAsync(_req); } } } diff --git a/src/Hosting/TestHost/src/TestServer.cs b/src/Hosting/TestHost/src/TestServer.cs index 872335f464..de10ff0081 100644 --- a/src/Hosting/TestHost/src/TestServer.cs +++ b/src/Hosting/TestHost/src/TestServer.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; +using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.TestHost { @@ -19,19 +20,22 @@ namespace Microsoft.AspNetCore.TestHost private ApplicationWrapper _application; /// - /// For use with IHostBuilder or IWebHostBuilder. + /// For use with IHostBuilder. /// - public TestServer() - : this(new FeatureCollection()) + /// + public TestServer(IServiceProvider services) + : this(services, new FeatureCollection()) { } /// - /// For use with IHostBuilder or IWebHostBuilder. + /// For use with IHostBuilder. /// + /// /// - public TestServer(IFeatureCollection featureCollection) + public TestServer(IServiceProvider services, IFeatureCollection featureCollection) { + Services = services ?? throw new ArgumentNullException(nameof(services)); Features = featureCollection ?? throw new ArgumentNullException(nameof(featureCollection)); } @@ -50,16 +54,19 @@ namespace Microsoft.AspNetCore.TestHost /// /// public TestServer(IWebHostBuilder builder, IFeatureCollection featureCollection) - : this(featureCollection) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } + Features = featureCollection ?? throw new ArgumentNullException(nameof(featureCollection)); + var host = builder.UseServer(this).Build(); host.StartAsync().GetAwaiter().GetResult(); _hostInstance = host; + + Services = host.Services; } public Uri BaseAddress { get; set; } = new Uri("http://localhost/"); @@ -73,6 +80,8 @@ namespace Microsoft.AspNetCore.TestHost } } + public IServiceProvider Services { get; } + public IFeatureCollection Features { get; } /// diff --git a/src/Hosting/TestHost/test/RequestBuilderTests.cs b/src/Hosting/TestHost/test/RequestBuilderTests.cs index 2a37015aae..01714f8d74 100644 --- a/src/Hosting/TestHost/test/RequestBuilderTests.cs +++ b/src/Hosting/TestHost/test/RequestBuilderTests.cs @@ -34,5 +34,19 @@ namespace Microsoft.AspNetCore.TestHost Assert.Equal("Test/Value", request.Content.Headers.ContentType.ToString()); }); } + + [Fact] + public void TestServer_PropertyShouldHoldTestServerInstance() + { + // Arrange + var builder = new WebHostBuilder().Configure(app => { }); + var server = new TestServer(builder); + + // Act + var requestBuilder = server.CreateRequest("/"); + + // Assert + Assert.Equal(server, requestBuilder.TestServer); + } } } diff --git a/src/Hosting/TestHost/test/TestServerTests.cs b/src/Hosting/TestHost/test/TestServerTests.cs index a2921dcf81..d05618cb26 100644 --- a/src/Hosting/TestHost/test/TestServerTests.cs +++ b/src/Hosting/TestHost/test/TestServerTests.cs @@ -11,10 +11,10 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Testing.xunit; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DiagnosticAdapter; using Microsoft.Extensions.Hosting; @@ -28,20 +28,22 @@ namespace Microsoft.AspNetCore.TestHost public class TestServerTests { [Fact] - public async Task GenericRawCreate() + public async Task GenericRawCreateAndStartHost_GetTestServer() { - var server = new TestServer(); using var host = new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder - .UseServer(server) + .ConfigureServices(services => + { + services.AddSingleton(serviceProvider => new TestServer(serviceProvider)); + }) .Configure(app => { }); }) .Build(); await host.StartAsync(); - var response = await server.CreateClient().GetAsync("/"); + var response = await host.GetTestServer().CreateClient().GetAsync("/"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -278,6 +280,58 @@ namespace Microsoft.AspNetCore.TestHost Assert.Throws(() => new TestServer(builder, null)); } + [Fact] + public void TestServerConstructorShouldProvideServicesFromPassedServiceProvider() + { + // Arrange + var serviceProvider = new ServiceCollection().BuildServiceProvider(); + + // Act + var testServer = new TestServer(serviceProvider); + + // Assert + Assert.Equal(serviceProvider, testServer.Services); + } + + [Fact] + public void TestServerConstructorShouldProvideServicesFromWebHost() + { + // Arrange + var testService = new TestService(); + var builder = new WebHostBuilder() + .ConfigureServices(services => services.AddSingleton(testService)) + .Configure(_ => { }); + + // Act + var testServer = new TestServer(builder); + + // Assert + Assert.Equal(testService, testServer.Services.GetService()); + } + + [Fact] + public async Task TestServerConstructorShouldProvideServicesFromHostBuilder() + { + // Arrange + var testService = new TestService(); + using var host = await new HostBuilder() + .ConfigureWebHost(webBuilder => + { + webBuilder + .UseTestServer() + .ConfigureServices(services => services.AddSingleton(testService)) + .Configure(_ => { }); + }) + .StartAsync(); + + // Act + // By calling GetTestServer(), a new TestServer instance will be instantiated + var testServer = host.GetTestServer(); + + // Assert + Assert.Equal(testService, testServer.Services.GetService()); + } + public class TestService { public string Message { get; set; } } public class TestRequestServiceMiddleware