TestProject 中包含的 TestStartup 继承自 API.Startup(包含在单独的项目中)导致 404 错误
TestStartup contained in a TestProject that inherits from API.Startup (contained in separate project) causes 404 error
我正在尝试将 StartupTest.cs 与 XUnit 和 TestServer 一起使用。
我已使用 Visual Studio 2017 15.9.3 遵循这些说明:
1) 创建一个新的解决方案。
2) 添加一个ASP.Net Core web 应用程序(web API) 到项目中。称之为API。无 Https 或 Docker.
3) 将 xUnit 测试项目 (.NET Core) 添加到解决方案中。称它为:XUnitTestProject1
4) 从 XUnit 项目添加对 Web API 项目的引用。
5) 在 XUnit 项目中安装以下 Nuget 包:
Microsoft.AspNetCore.TestHost、Microsoft.Extensions.PlatformAbstractions 和 Microsoft.AspNetCore.All。
6) 将下面的class添加到Unit Test项目中(注意Startup是来自web api项目的Startup.cs):
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) 将此测试添加到测试项目中:
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) 运行 测试并收到成功响应(200)。到目前为止一切都很好。
10) 接下来就是在Unit Test项目中创建一个TestStartupclass:
public class StartupTest : Startup
{
public StartupTest(IConfiguration env) : base(env)
{
}
}
注意:我意识到这个 Startup class 目前毫无意义 - 我确实计划在它工作后重写一些方法。
11) 修改第 6 点中的代码,即更改此行:
.UseStartup<Startup>();
至:
.UseStartup<StartupTest>();
12) 运行 再次测试并看到 404 响应而不是 200 响应。
为什么我在添加 TestStartup 后看到 404 响应 class。
TestStartup 继承自 API.Startup。
我在这里找到了答案:https://github.com/aspnet/Mvc/issues/5992。我只需按如下方式覆盖 StartupTest 中的 ConfigureServices:
public override void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddApplicationPart(typeof(ValuesController).Assembly);
}
在你的:
var builder = new WebHostBuilder()
...
.ConfigureServices(InitializeServices)
....;
并将此方法添加到您的 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);
}
我正在尝试将 StartupTest.cs 与 XUnit 和 TestServer 一起使用。
我已使用 Visual Studio 2017 15.9.3 遵循这些说明:
1) 创建一个新的解决方案。
2) 添加一个ASP.Net Core web 应用程序(web API) 到项目中。称之为API。无 Https 或 Docker.
3) 将 xUnit 测试项目 (.NET Core) 添加到解决方案中。称它为:XUnitTestProject1
4) 从 XUnit 项目添加对 Web API 项目的引用。
5) 在 XUnit 项目中安装以下 Nuget 包: Microsoft.AspNetCore.TestHost、Microsoft.Extensions.PlatformAbstractions 和 Microsoft.AspNetCore.All。
6) 将下面的class添加到Unit Test项目中(注意Startup是来自web api项目的Startup.cs):
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) 将此测试添加到测试项目中:
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) 运行 测试并收到成功响应(200)。到目前为止一切都很好。
10) 接下来就是在Unit Test项目中创建一个TestStartupclass:
public class StartupTest : Startup
{
public StartupTest(IConfiguration env) : base(env)
{
}
}
注意:我意识到这个 Startup class 目前毫无意义 - 我确实计划在它工作后重写一些方法。
11) 修改第 6 点中的代码,即更改此行:
.UseStartup<Startup>();
至:
.UseStartup<StartupTest>();
12) 运行 再次测试并看到 404 响应而不是 200 响应。
为什么我在添加 TestStartup 后看到 404 响应 class。
TestStartup 继承自 API.Startup。
我在这里找到了答案:https://github.com/aspnet/Mvc/issues/5992。我只需按如下方式覆盖 StartupTest 中的 ConfigureServices:
public override void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddApplicationPart(typeof(ValuesController).Assembly);
}
在你的:
var builder = new WebHostBuilder()
...
.ConfigureServices(InitializeServices)
....;
并将此方法添加到您的 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);
}