You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 7单元测试前如何启动指定端口的REST API服务?

在.NET 7单元测试前启动指定端口的REST API服务

针对你的场景,有两种常用的实现方式,都能在单元测试执行前启动API服务并指定端口:

方案一:使用WebApplicationFactory(官方集成测试推荐)

这是.NET官方提供的集成测试工具,能自动托管API并处理生命周期,还支持端口配置。

步骤:

  1. 在单元测试项目中添加对REST API项目的项目引用。
  2. 如果API项目的Program.cs是顶级语句(默认模板生成),需要在API项目的Program.cs末尾添加一行,让Program类可被测试项目访问:
public partial class Program { }
  1. 在测试项目中创建自定义的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;
    }
}
  1. 在测试类中使用该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的主机实例,在测试开始前启动,测试结束后销毁。

步骤:

  1. 同样给测试项目添加API项目的引用,并确保Program类可访问。
  2. 创建一个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();
    }
}
  1. 在测试类中注入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é

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:10:33