Как я могу выполнить модульное тестирование обработчиков ребусов, если обработчик обработан, когда включен параметр secondLevelRetriesEnabled

#rebus

Вопрос:

Я нахожусь в процессе написания некоторых модульных тестов для моих обработчиков ребусов. Я решил включить secondLevelRetriesEnabled , что приводит к IFailed<TMessage> публикации при возникновении исключения в обработчике.

Мое определение класса обработчика таково:

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

Когда я запускаю процесс, все работает так, как ожидалось; сложность возникает при попытке написать модульный тест на secondLevelRetriesEnabled поведение.

Когда мой модульный тест вызывает 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. Насколько я могу судить, нет ничего HandleFixture подобного тому SagaFixture , что поддерживает fixture.DeliverFailed(new OrdinaryMessage(...), new ApplicationException("oh no"));

Ответ №1:

Я не думаю, что на данный момент существует действительно элегантный способ, но один из способов, которым вы могли бы обернуться и, возможно, сделать себя красивыми, — это сделать что-то вроде этого:

 // 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
 

Это явно то, что могло бы быть лучше, поэтому не стесняйтесь поднимать вопрос в Ребусе.Хранилище TestHelpers, которое было бы подходящим местом для проживания для какого-то решения этой проблемы.