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

启用secondLevelRetriesEnabled时如何单元测试Rebus的IFailed<Message>处理器

解决方案

你遇到的报错本质是直接手动调用处理器Handle方法时,没有初始化Rebus依赖的消息上下文。真实运行时Rebus分发消息会自动将当前消息上下文绑定到异步本地存储,而单元测试里直接调用Handle时缺少这一步,导致bus.Advanced.TransportMessage.Deadletter找不到对应的上下文信息。

方法1:使用FakeMessageContext手动绑定上下文(推荐)

Rebus.Testing 包内置了FakeMessageContext类,可以快速模拟消息上下文,只需要在调用处理器方法前将上下文绑定到当前异步环境即可。
示例代码:

// 1. 构造测试用的IFailed<TMessage>实例
var ordinaryMessage = new OrdinaryMessage();
var failedMessage = new Failed<OrdinaryMessage>(
    message: ordinaryMessage,
    errorDescription: "Failed to handle message after 2 deferrals",
    numberOfDeliveryAttempts: 2
);

// 2. 初始化FakeBus和你的处理器
var fakeBus = new FakeBus();
var handler = new Handler<OrdinaryMessage>(fakeBus);

// 3. 绑定FakeMessageContext到当前异步上下文,using块内的代码都能读取到该上下文
using var _ = new FakeMessageContext(failedMessage);

// 4. 调用处理器的IFailed消息处理方法
await handler.Handle(failedMessage);

// 5. 断言死信逻辑符合预期
var deadlettered = fakeBus.Advanced.DeadletteredMessages.Single();
Assert.Equal(ordinaryMessage, deadlettered.Message);

方法2:封装自定义测试夹具(复用度更高)

如果需要经常测试失败消息处理逻辑,可以自行封装简易的测试夹具,模拟你想要的DeliverFailed能力,示例封装逻辑:

public class HandlerFixture<THandler, TMessage> where THandler : IHandleMessages<IFailed<TMessage>>
{
    public FakeBus Bus { get; } = new FakeBus();
    public THandler Handler { get; }

    public HandlerFixture(THandler handler)
    {
        Handler = handler;
    }

    public async Task DeliverFailed(TMessage message, Exception exception, int deliveryAttempts = 2)
    {
        var failedMessage = new Failed<TMessage>(
            message: message,
            errorDescription: exception.Message,
            numberOfDeliveryAttempts: deliveryAttempts
        );
        using var _ = new FakeMessageContext(failedMessage);
        await Handler.Handle(failedMessage);
    }
}

使用方式和你期望的一致:

var fixture = new HandlerFixture<Handler<OrdinaryMessage>, OrdinaryMessage>(new Handler<OrdinaryMessage>(new FakeBus()));
await fixture.DeliverFailed(new OrdinaryMessage(), new ApplicationException("oh no"));
// 后续断言fixture.Bus的死信数据即可

内容的提问来源于stack exchange,提问作者Y0rk1e

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:06:01