问题
I am trying to use a StartupTest.cs with XUnit and TestServer.
I have followed these instructions using Visual Studio 2017 15.9.3:
1) Create a new solution.
2) Add an ASP.Net Core web application (web API) to the project. Call it API. No Https or Docker.
3) Add a xUnit Test project (.NET Core) to the solution. Call it: XUnitTestProject1
4) Add a reference to the Web API project from the XUnit project.
5) Install the following Nuget packages in the XUnit project: Microsoft.AspNetCore.TestHost, Microsoft.Extensions.PlatformAbstractions and Microsoft.AspNetCore.All.
6) Add the following class to the Unit Test project (note that Startup is the Startup.cs from the web api project):
using API;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.PlatformAbstractions;
using System;
using System.IO;
using System.Net.Http;
namespace XUnitTestProject1
{
public class TestServerFixture : IDisposable
{
private readonly TestServer _testServer;
public HttpClient Client { get; }
public TestServerFixture()
{
var builder = new WebHostBuilder()
.UseContentRoot(GetContentRootPath())
.UseEnvironment("Test")
.UseStartup<Startup>(); // Uses Start up class from your API Host project to configure the test server
_testServer = new TestServer(builder);
Client = _testServer.CreateClient();
}
private string GetContentRootPath()
{
var testProjectPath = PlatformServices.Default.Application.ApplicationBasePath;
var relativePathToHostProject = @"..\..\..\..\..\..\TestHost";
return Path.Combine(testProjectPath, relativePathToHostProject);
}
public void Dispose()
{
Client.Dispose();
_testServer.Dispose();
}
}
}
8) Add this test to the test project:
using System;
using Xunit;
namespace XUnitTestProject1
{
public class UnitTest1
{
private readonly TestServerFixture _fixture;
public UnitTest1(TestServerFixture fixture)
{
_fixture = new TestServerFixture(); //Make sure class implements IClassFixture.
}
[Fact]
public async System.Threading.Tasks.Task Test1Async()
{
var response = await _fixture.Client.GetAsync("api/Values");
response.EnsureSuccessStatusCode();
var responseStrong = await response.Content.ReadAsStringAsync();
}
}
}
9) Run the test and receive a successful response (200). All is well up to this point.
10) The next step is to create a TestStartup class in the Unit Test project:
public class StartupTest : Startup
{
public StartupTest(IConfiguration env) : base(env)
{
}
}
Note: I realise this Startup class is pointless at the moment - I do plan to override some methods once I get it working.
11) Amend the code in point 6 i.e. change this line:
.UseStartup<Startup>();
to:
.UseStartup<StartupTest>();
12) Run the test again and see a 404 response instead of 200 response.
Why do I see a 404 response after I add the TestStartup class.
TestStartup inherits from API.Startup.
回答1:
I found the answer here: https://github.com/aspnet/Mvc/issues/5992. I simply had to override ConfigureServices in StartupTest as follows:
public override void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddApplicationPart(typeof(ValuesController).Assembly);
}
回答2:
In your:
var builder = new WebHostBuilder()
...
.ConfigureServices(InitializeServices)
....;
And add this method to your TestServerFixture.cs
protected virtual void InitializeServices(IServiceCollection services)
{
var startupAssembly = typeof(TestStartup).GetTypeInfo().Assembly;
var manager = new ApplicationPartManager();
manager.ApplicationParts.Add(new AssemblyPart(startupAssembly));
manager.ApplicationParts.Add(new AssemblyPart(typeof(ValuesController).Assembly));
manager.FeatureProviders.Add(new ControllerFeatureProvider());
manager.FeatureProviders.Add(new ViewComponentFeatureProvider());
services.AddSingleton(manager);
}
来源:https://stackoverflow.com/questions/53681935/teststartup-contained-in-a-testproject-that-inherits-from-api-startup-contained