gpt4 book ai didi

c# - 用最小起订量模拟 MediatR 3

转载 作者:可可西里 更新时间:2023-11-01 09:02:40 28 4
gpt4 key购买 nike

我们最近开始使用 MediatR 来整理 Controller 操作,因为我们重构了面向大型客户的门户并将其全部转换为 C#。作为其中的一部分,我们也在增加我们的单元测试覆盖率,但我在尝试模拟 MediatR 本身时遇到了问题。

该命令做了很多事情来启动一个过程,其中一部分是发送通知。通知本身由其自己的处理程序处理,因此将接受其自己的单元测试,因此我想模拟 MediatR,以便 this.mediator.Send(message) 调用不会真正执行任何事物。处理程序确实返回一个对象,但我们在此上下文中不关心它,因此出于所有意图和目的,我们将其视为 void 返回。我只想验证 Send 作为测试的一部分被调用了一次。但是,Send 方法抛出一个 NullReferenceException,我不知道为什么。

从版本 3 开始,MediatR 现在在 Send 上采用第二个可选参数,一个 CancellationToken,并且表达式树要求您显式设置它们,因此您必须指定一个值.我以前没有遇到过这种情况,在我看来我觉得这可能是问题的一部分,但这可能是我的混淆。

这是一个简化的插图。

停止

public class TransferHandler : IAsyncRequestHandler<TransferCommand, TransferResult>
{
private readonly IMediator mediator;

public TransferHandler(IMediator mediator)
{
this.mediator = mediator;
}

public async Task<TransferResult> Handle(TransferCommand message)
{
// Other stuff.
var notification = new TransferNotificationCommand()
{
ClientId = message.clientId,
OfficeId = message.OfficeId,
AuthorityFileId = letter?.Id
};

await this.mediator.Send(notification); // <=== This is where we get a NullReferenceException, even though nothing is actually null (that I can see).

return new TransferResult()
{
Transfer = transfer,
FileId = letter?.Id
}
}
}

测试

public class TransferHandlerTests
{
[Theory]
[AutoData]
public async void HandlerCreatesTransfer(Mock<IMediator> mockMediator)
{
// Note that default(CancellationToken) is the default value of the optional argument.
mockMediator.Setup(m => m.Send(It.IsAny<TransferNotificationCommand>(), default(CancellationToken))).Verifiable("Notification was not sent.");

var handler = new TransferHandler(mockMediator.Object);

var actual = await handler.Handle(message);

mockMediator.Verify(x => x.Send(It.IsAny<CreateIsaTransferNotificationCommand>(), default(CancellationToken)), Times.Once());
}
}

我错过了什么?我觉得我在某个地方犯了一个根本性的错误,但我不确定在哪里。

最佳答案

您需要在 Send 方法返回任务时处理异步操作的等待。

/// <summary>
/// Asynchronously send a request to a single handler
/// </summary>
/// <typeparam name="TResponse">Response type</typeparam>
/// <param name="request">Request object</param>
/// <param name="cancellationToken">Optional cancellation token</param>
/// <returns>A task that represents the send operation. The task result contains the handler response</returns>
Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Asynchronously send a request to a single handler without expecting a response
/// </summary>
/// <param name="request">Request object</param>
/// <param name="cancellationToken">Optional cancellation token</param>
/// <returns>A task that represents the send operation.</returns>
Task Send(IRequest request, CancellationToken cancellationToken = default(CancellationToken));

这意味着您需要让模拟返回一个任务以允许异步进程继续流程

mediator
.Setup(m => m.Send(It.IsAny<TransferNotificationCommand>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new Notification()) //<-- return Task to allow await to continue
.Verifiable("Notification was not sent.");

//...other code removed for brevity

mediator.Verify(x => x.Send(It.IsAny<CreateIsaTransferNotificationCommand>(), It.IsAny<CancellationToken>()), Times.Once());

关于c# - 用最小起订量模拟 MediatR 3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43249816/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com