基于eShopOnContainers的微服务功能测试:批量运行失败单独运行正常
微服务测试并行失败问题排查与修复
核心排查点
- 端口/资源抢占:并行运行时,多个测试项目可能抢占同一端口或共享资源,导致服务启动失败。
- 全局状态污染:静态类、全局变量(如事件总线实例)在测试间共享状态,导致后续测试依赖前序测试的脏数据。
- 事件总线冲突:集成事件总线被重复注册或订阅,导致事件路由混乱。
- 数据库竞争:多个测试共用同一数据库,出现数据插入/修改冲突。
具体修复方案
1. 隔离测试端口与服务实例
每个服务测试项目的TestStartup指定独立端口,避免端口冲突:
// Basket测试启动类 public class BasketTestStartup { public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // ...其他配置 } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseUrls("http://localhost:5003") // 独立端口 .UseStartup<BasketTestStartup>(); }
Ordering和Catalog测试同理,分别使用5004、5005等不同端口。
2. 重置全局共享状态
在每个测试类的初始化方法中,清理全局资源(如事件总线):
[TestInitialize] public void TestSetup() { var eventBus = ServiceProvider.GetRequiredService<IEventBus>(); if (eventBus is InMemoryEventBus inMemoryBus) { inMemoryBus.ResetSubscriptions(); inMemoryBus.ClearEventQueue(); } }
3. 独立测试数据库
为每个服务测试分配专属数据库,避免数据竞争:
- 使用SQL Server时,每个测试用唯一命名的数据库:
// Basket测试的appsettings.json "ConnectionStrings": { "BasketDB": "Server=(localdb)\\mssqllocaldb;Database=BasketTest_{Guid.NewGuid()};Trusted_Connection=True;" } - 使用内存数据库时,确保每个测试实例独立:
services.AddDbContext<BasketDbContext>(options => options.UseInMemoryDatabase($"BasketTestDb_{Guid.NewGuid()}"));
4. 避免跨服务共享基类
每个服务测试项目维护自己的ScenarioBase和TestStartup,确保依赖注入容器完全隔离,不共享任何服务实例。
内容的提问来源于stack exchange,提问作者Kaveh Naseri
相关产品推荐
相关产品推荐

