我正在尝试为基于CQRS / ES模式的MVC Core 2.2应用程序构建xUnit Test项目。我将MediatR用作MVC应用程序中CQRS / ES模式的一部分。
在我要测试的命令之一中,一旦客户记录已更新,我就注入MediatR来发布事件。有点像这样:
public class UpdateCustomerCommandHandler : IRequestHandler<UpdateCustomerCommand>
{
public IMediator Mediator { get; set; }
public UpdateCustomerCommandHandler(IMediator mediator)
{
Mediator = mediator;
}
public Task<Unit> Handle(UpdateCustomerCommand request, CancellationToken cancellationToken)
{
//do some stuff
Mediator.Publish(new CustomersChanged());
return Task.FromResult(new Unit());
}
}
Run Code Online (Sandbox Code Playgroud)
对此命令编写单元测试时,显然,我还必须创建MediatR(或模型)实例,然后在测试执行期间将其传递给命令。
[Fact]
public async void UpdateCustomerCommand_CustomerDataUpdatedOnDatabase()
{
//Arange
var mediator = new Mediator(); // doesn't work that way..
UpdateCustomerCommand command = new UpdateCustomerCommand();
UpdateCustomerCommandHandler handler = new UpdateCustomerCommandHandler(mediator);
//Act
Unit x = await handler.Handle(command, new System.Threading.CancellationToken());
//Asert
//Do the assertion
}
Run Code Online (Sandbox Code Playgroud)
但是,实例化MediatR(在MVC应用程序之外,我可以在其中使用现有的依赖注入实现)似乎并不那么简单,坦白地说,我实际上不了解如何在测试方法中进行操作。
我知道我可能会使用MediatR已经为其提供实现的依赖注入框架(Ninject等),但是我实际上不想在我的单元测试中使用除MediatR之外的任何其他第三方库,只是为了创建实例。
有没有一种更简单的实例化MediatR的方法,我可能已经对此进行了监督?
为了扩展已接受的答案,如果您绝对需要使用 MediatR 测试两个服务之间的交互,您始终可以使用回调来最小化每个发布/处理程序对:
_mediator = new Mock<IMediator>();
_mediator.Setup(m => m.Publish(It.IsAny<YourNotification>(), It.IsAny<CancellationToken>()))
.Callback<YourNotification, CancellationToken>((notification, cToken) =>
_yourHandlerService.Handle(notification, cToken));
Run Code Online (Sandbox Code Playgroud)
上面的代码基本上是说如果 _mediator 获取YourNotificationviaPublish方法,那么它会将其转发给_yourHandlerServiceviaHandle方法。您可以对要处理的Setup每种类型的中介者重复此操作。INotification
你在右边线用or a mockup-你需要嘲笑的IMediator
这里有一些模拟库:
最小起订量是最受欢迎的一种,因此,以您的测试为例:
[Fact]
public async void UpdateCustomerCommand_CustomerDataUpdatedOnDatabase()
{
//Arange
var mediator = new Mock<IMediator>();
UpdateCustomerCommand command = new UpdateCustomerCommand();
UpdateCustomerCommandHandler handler = new UpdateCustomerCommandHandler(mediator.Object);
//Act
Unit x = await handler.Handle(command, new System.Threading.CancellationToken());
//Asert
//Do the assertion
//something like:
mediator.Verify(x=>x.Publish(It.IsAny<CustomersChanged>()));
}
Run Code Online (Sandbox Code Playgroud)