.NET 7单元测试前如何启动指定端口的REST API服务?
在.NET 7单元测试前启动指定端口的REST API服务
针对你的场景,有两种常用的实现方式,都能在单元测试执行前启动API服务并指定端口:
方案一:使用WebApplicationFactory(官方集成测试推荐)
这是.NET官方提供的集成测试工具,能自动托管API并处理生命周期,还支持端口配置。
步骤:
- 在单元测试项目中添加对REST API项目的项目引用。
- 如果API项目的
Program.cs是顶级语句(默认模板生成),需要在API项目的Program.cs末尾添加一行,让Program类可被测试项目访问:
public partial class Program { }
- 在测试项目中创建自定义的
WebApplicationFactory,指定端口:
public class ApiTestFactory : WebApplicationFactory<Program> { private int _assignedPort; protected override void ConfigureWebHost(IWebHostBuilder builder) { // 指定固定端口,或者用0让系统分配可用端口 builder.UseUrls("http://localhost:5000"); base.ConfigureWebHost(builder); } // 若使用动态端口,通过此方法获取实际分配的端口 public int GetAssignedPort() { if (_assignedPort == 0) { _assignedPort = new Uri(Server.BaseAddress).Port; } return _assignedPort; } }
- 在测试类中使用该Factory,初始化REST客户端:
public class ApiIntegrationTests : IClassFixture<ApiTestFactory> { private readonly YourRestClient _restClient; public ApiIntegrationTests(ApiTestFactory factory) { // 固定端口直接指定,动态端口则调用GetAssignedPort()获取 var apiBaseUrl = "http://localhost:5000"; // 动态端口写法:var apiBaseUrl = $"http://localhost:{factory.GetAssignedPort()}"; _restClient = new YourRestClient(apiBaseUrl); } [Fact] public async Task Get_Data_ReturnsValidResult() { // 通过REST客户端调用API接口 var result = await _restClient.FetchDataAsync(); Assert.NotNull(result); // 其他断言逻辑 } }
方案二:手动启动IHost(自定义生命周期控制)
如果需要更灵活的主机配置,可手动创建并启动API的主机实例,在测试开始前启动,测试结束后销毁。
步骤:
- 同样给测试项目添加API项目的引用,并确保
Program类可访问。 - 创建一个Fixture类管理主机生命周期:
public class ApiHostFixture : IAsyncLifetime { private IHost _apiHost; public string ApiBaseUrl { get; private set; } = "http://localhost:5000"; public async Task InitializeAsync() { // 构建并启动API主机 var hostBuilder = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Program>() .UseUrls(ApiBaseUrl); }); _apiHost = hostBuilder.Build(); await _apiHost.StartAsync(); } public async Task DisposeAsync() { // 测试结束后停止并释放主机资源 await _apiHost.StopAsync(); _apiHost.Dispose(); } }
- 在测试类中注入Fixture,初始化REST客户端:
public class ApiUnitTests : IClassFixture<ApiHostFixture> { private readonly YourRestClient _restClient; public ApiUnitTests(ApiHostFixture fixture) { _restClient = new YourRestClient(fixture.ApiBaseUrl); } [Fact] public async Task Post_Data_CreatesSuccessfully() { var newData = new TestData { Name = "Test" }; var response = await _restClient.CreateDataAsync(newData); Assert.Equal(HttpStatusCode.Created, response.StatusCode); } }
注意事项:
- 固定端口可能存在占用问题,推荐使用动态端口(
UseUrls("http://localhost:0")),然后从主机实例中获取实际端口。 - 测试前确保API项目的依赖(如数据库、配置)已准备好,可在Factory或Host配置中替换为测试用的依赖(比如内存数据库)。
- 若使用xUnit,
IClassFixture会确保Fixture在测试类的所有测试执行前初始化,测试结束后销毁,避免重复启动主机。
内容的提问来源于stack exchange,提问作者jéjé
相关产品推荐
相关产品推荐

