.NET 7 REST API集成测试:Testcontainers 3.0.0配置SQL Server遇阻
解决方案:.NET 7 REST API集成测试中使用SQL Server Testcontainers(3.0.0版本)
1. 安装正确的NuGet包
Testcontainers 3.x版本采用模块化设计,需安装SQL Server专用包替代基础包:
Install-Package Testcontainers.MsSql -Version 3.0.0
或通过.NET CLI:
dotnet add package Testcontainers.MsSql --version 3.0.0
2. 正确构建SQL Server容器(替代废弃的ContainerBuilder)
3.x版本中直接使用MsSqlBuilder封装SQL Server容器的所有必要配置,无需手动拼接环境变量和等待策略:
using Testcontainers.MsSql; using Microsoft.EntityFrameworkCore; public class ApiIntegrationTests : IAsyncLifetime { private readonly MsSqlContainer _dbContainer; private AppDbContext _dbContext; public ApiIntegrationTests() { _dbContainer = new MsSqlBuilder() .WithPassword("MyStrongPass123!") // 需符合SQL Server密码规则:8位以上,含大小写、数字、特殊字符 .WithDatabase("LocalTestDb") // 容器启动时自动创建该数据库 .Build(); } public async Task InitializeAsync() { // 启动容器并等待服务就绪 await _dbContainer.StartAsync(); // 配置EF Core上下文,使用容器自动生成的连接字符串 var dbOptions = new DbContextOptionsBuilder<AppDbContext>() .UseSqlServer(_dbContainer.GetConnectionString()) .Options; _dbContext = new AppDbContext(dbOptions); // 执行EF迁移,自动创建表结构 await _dbContext.Database.MigrateAsync(); } public async Task DisposeAsync() { await _dbContext.DisposeAsync(); await _dbContainer.StopAsync(); await _dbContainer.DisposeAsync(); } // 集成测试用例示例 [Fact] public async Task Post_Entity_ReturnsCreatedEntity() { // 测试逻辑:先往数据库插测试数据,再调用API验证结果 var testItem = new TestEntity { Name = "Test Item" }; _dbContext.TestEntities.Add(testItem); await _dbContext.SaveChangesAsync(); // 初始化API客户端并调用接口,此处省略客户端创建代码 // var response = await _apiClient.PostAsync("/api/items", testItem); // Assert.Equal(HttpStatusCode.Created, response.StatusCode); } }
3. 你之前代码的报错原因及修复
- 端口冲突:手动指定
WithPortBinding(49401, 1433)会占用固定端口,若端口已被其他程序占用则触发Conflict错误。Testcontainers默认自动分配随机可用端口,无需手动绑定。 - 容器启动失败:SA密码
MyStrongPassword不符合SQL Server复杂度要求,导致容器启动失败,进而触发"容器未运行"错误。需调整密码包含大小写、数字和特殊字符。 - 等待策略错误:手动配置的
UntilCommandIsCompleted命令引号格式错误,且缺少SQL Server服务就绪的完整等待逻辑,MsSqlBuilder已内置完善的等待机制。
4. 数据库/表创建说明
无需手动创建:
- 通过
MsSqlBuilder.WithDatabase()可指定容器启动时自动创建目标数据库。 - 借助EF Core的
Database.MigrateAsync(),会自动应用所有迁移脚本生成表结构;若未使用迁移,可改用Database.EnsureCreatedAsync()(迁移更适合长期维护场景)。
内容的提问来源于stack exchange,提问作者Ezequiel Irigoyen
相关产品推荐
相关产品推荐

