.NET5测试项目的依赖注入(DI)注册代码应放在哪里实现全局单次调用?
解决方案
主流.NET测试框架没有和Web项目完全一致的Program.cs全局入口,但有多种方式可以实现DI注册逻辑全局仅执行一次,避免重复初始化的性能开销:
通用无框架绑定方案
直接将IHost的初始化逻辑放到BaseTest的静态构造函数中即可,静态构造函数在整个测试生命周期内只会触发一次,所有测试类实例共享同一个DI容器:
public class BaseTest { protected static readonly IHost _testHost; // 按需暴露需要的服务,或者直接暴露Services属性供子类取服务 protected IMediator _mediator => _testHost.Services.GetRequiredService<IMediator>(); static BaseTest() { _testHost = Host.CreateDefaultBuilder() .UseSerilog() .ConfigureServices((hostContext, services) => { // 原有的所有DI注册逻辑原封不动迁移到此处 }) .Build(); // 如果你的测试依赖后台运行的宿主服务,可加这句启动宿主 _ = _testHost.RunAsync(); } // 可选:测试全部完成后释放资源 ~BaseTest() { _testHost?.Dispose(); } }
提示:如果存在少量需要隔离DI容器的特殊测试,不要继承该BaseTest,单独写小范围的初始化逻辑即可,避免单例容器导致测试互相影响。
对应测试框架的原生全局初始化方案
如果需要更规范的全局生命周期控制,可以使用对应测试框架提供的原生钩子:
- xUnit:实现
ICollectionFixture<T>或者程序集级别的AssemblyFixture(xUnit 2.4及以上版本支持),把Host初始化逻辑放到Fixture类中,所有测试类关联该Fixture即可复用容器 - NUnit:创建全局SetUp类,给初始化方法标记
[OneTimeSetUp]特性,可实现整个程序集测试运行前仅执行一次 - MSTest:给静态初始化方法标记
[AssemblyInitialize]特性,程序集启动时自动执行一次注册逻辑
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

