启用 secondLevelRetriesEnabled 时如何对 Rebus 处理程序 IFailed<Message> 进行单元测试

How do I unit test Rebus handlers IFailed<Message> handle when secondLevelRetriesEnabled is enabled

我正在为我的 Rebus 处理程序编写一些单元测试。我选择启用 secondLevelRetriesEnabled,这会导致在处理程序中抛出异常时发布 IFailed<TMessage>

我的处理程序 class 定义是:

Handler<T> : IHandleMessages<T>, IHandleMessages<IFailed<T>>

当我 运行 过程一切正常时;尝试为 secondLevelRetriesEnabled 行为编写单元测试时会遇到困难。

当我的单元测试调用我的 Handler 的 IFailed<TMessage> 方法导致调用 await bus.Advanced.TransportMessage.Deadletter(message) 时,我从 FakeBus.

中得到以下异常
"Attempted to dead-letter the current message using error details 'Failed to handle message after 2 deferrals', but no message context could be found! This is probably a sign that this method was called OUTSIDE of a Rebus handler, or on a separate, disconnected thread somehow. Please only call this method inside Rebus handlers."

在测试 IFailed 消息句柄时,有人可以指出正确的方向来解决 Deadletter 队列异常。据我所知,没有 HandleFixture 像支持 fixture.DeliverFailed(new OrdinaryMessage(...), new ApplicationException("oh no"));

SagaFixture

我认为目前没有真正优雅的方法,但您可以总结并可能让自己漂亮的一种方法是做这样的事情:

// this is the message we're pretending to be handling
var transportMessage = new TransportMessage(...);

using var scope = new RebusTransactionScope();

var transactionContext = scope.TransactionContext;
var incomingStepContext = new IncomingStepContext(transportMessage, transactionContext);

// fake incoming step context here:
transactionContext.Items[StepContext.StepContextKey] = incomingStepContext;

// now MessageContext.Current should return a proper IMessageContext

//< exercise your handler here

//< check incomingStepContext here

这显然可以做得更好,所以请随时在 Rebus.TestHelpers repository 中提出问题,这将是解决此问题的合适地方。