如何测试MediatR请求是否已完成注册?
验证MediatR请求注册的单元测试方案
问题背景
我在多项目解决方案中使用MediatR,每个项目生成独立EXE文件,各EXE会注册不同的IRequest请求——部分来自公共项目,部分来自EXE项目本身。之前因忘记注册某个程序集,出现单元测试全部通过但程序运行时无法找到部分请求的情况,希望编写单元测试验证所有必要请求已在程序中正确注册。
实现思路
IRequest本身不是可直接通过GetService<T>获取的服务,核心验证逻辑要围绕MediatR是否能找到对应请求的处理程序,以及目标程序集是否被正确纳入扫描范围展开。
具体实现方案
方案1:单个请求的注册验证
通过IMediator尝试发送请求,若未注册对应处理程序会抛出异常,以此验证注册有效性:
// 初始化应用Host,和生产环境启动逻辑一致 var host = MyApp.CreateHostBuilder().Build(); await host.StartAsync(); try { var mediator = host.Services.GetRequiredService<IMediator>(); // 构造待验证的请求实例 var testRequest = new MyRequest(); // 尝试发送请求,未注册处理程序会抛出InvalidOperationException await mediator.Send(testRequest); // 或者更轻量的方式:直接检查处理程序类型是否存在 var handlerType = mediator.GetHandlerType(typeof(MyRequest)); Assert.That(handlerType, Is.Not.Null); } finally { await host.StopAsync(); }
方案2:批量验证指定程序集内的所有请求
通过反射扫描目标程序集内的所有IRequest类型,逐个验证是否存在对应的处理程序:
var host = MyApp.CreateHostBuilder().Build(); await host.StartAsync(); try { var mediator = host.Services.GetRequiredService<IMediator>(); // 指定要验证的目标程序集(比如公共项目或当前EXE的程序集) var targetAssembly = typeof(MyRequest).Assembly; // 扫描程序集中所有实现IRequest的非抽象、非接口类型 var requestTypes = targetAssembly.GetTypes() .Where(t => !t.IsAbstract && !t.IsInterface && typeof(IRequest).IsAssignableFrom(t)); foreach (var requestType in requestTypes) { var handlerType = mediator.GetHandlerType(requestType); Assert.That(handlerType, Is.Not.Null, $"请求类型 {requestType.FullName} 未注册处理程序"); } } finally { await host.StopAsync(); }
方案3:验证MediatR的程序集扫描范围
如果问题根源是漏加程序集注册,可以直接验证目标程序集是否在MediatR的扫描列表中:
var host = MyApp.CreateHostBuilder().Build(); await host.StartAsync(); try { var mediatorOptions = host.Services.GetService<IOptions<MediatROptions>>()?.Value; Assert.That(mediatorOptions, Is.Not.Null); // 检查目标程序集是否被纳入扫描范围 var targetAssembly = typeof(MyRequest).Assembly; var isAssemblyRegistered = mediatorOptions.Assemblies.Contains(targetAssembly); Assert.That(isAssemblyRegistered, Is.True, $"程序集 {targetAssembly.FullName} 未被MediatR扫描注册"); } finally { await host.StopAsync(); }
关键提示
- 测试时必须启动真实的Host,确保服务注册逻辑和生产环境完全一致
- 对于不需要执行实际业务逻辑的请求,可以编写空的测试处理程序,或在测试中模拟处理逻辑
- 批量验证方案适合覆盖公共项目的所有请求,避免遗漏个别类型的注册
内容的提问来源于stack exchange,提问作者Creak
相关产品推荐
相关产品推荐

