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

如何测试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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 11:26:09