如何将 Mediatr 实例化为单元测试的一部分?
How to instantiate Mediatr as part of a Unit Test?
我正在尝试为基于 CQRS/ES 模式的 MVC Core 2.2 应用程序构建 xUnit 测试项目。我在 MVC 应用程序中使用 MediatR 作为我的 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());
}
}
为此命令编写单元测试时,我显然还必须创建一个 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
}
然而,实例化 MediatR(在 MVC 应用程序之外,我可以在其中利用现有的依赖注入实现)似乎并不那么简单,坦率地说,我实际上不明白我可以在我的测试方法中做什么。
我知道我可能会使用 MediatR 已经为其提供实现的依赖注入框架(Ninject,等等),但实际上我不想在我的单元中使用任何其他第三方库除了 MediatR 之外的测试,只是为了创建一个实例。
是否有更简单的方法来实例化我可能已经监督过的 MediatR?
你在 or a mockup
的正确路线上 - 你需要 mock IMediator
那里有一些模拟库:
- 起订量
- FakeItEasy
- N替换
Moq 是最受欢迎的之一,因此,以您的测试为例:
[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>()));
}
为了扩展已接受的答案,如果您绝对需要使用 MediatR 测试两个服务之间的交互,您始终可以使用回调对每个 publish/handler 对进行最小起订:
_mediator = new Mock<IMediator>();
_mediator.Setup(m => m.Publish(It.IsAny<YourNotification>(), It.IsAny<CancellationToken>()))
.Callback<YourNotification, CancellationToken>((notification, cToken) =>
_yourHandlerService.Handle(notification, cToken));
上面的代码,基本上是说如果 _mediator 通过 Publish
方法获得 YourNotification
,那么它将通过 Handle
方法将它转发给 _yourHandlerService
。您可以为要处理的每种类型的调解器 INotification
重复 Setup
。
我正在尝试为基于 CQRS/ES 模式的 MVC Core 2.2 应用程序构建 xUnit 测试项目。我在 MVC 应用程序中使用 MediatR 作为我的 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());
}
}
为此命令编写单元测试时,我显然还必须创建一个 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
}
然而,实例化 MediatR(在 MVC 应用程序之外,我可以在其中利用现有的依赖注入实现)似乎并不那么简单,坦率地说,我实际上不明白我可以在我的测试方法中做什么。
我知道我可能会使用 MediatR 已经为其提供实现的依赖注入框架(Ninject,等等),但实际上我不想在我的单元中使用任何其他第三方库除了 MediatR 之外的测试,只是为了创建一个实例。
是否有更简单的方法来实例化我可能已经监督过的 MediatR?
你在 or a mockup
的正确路线上 - 你需要 mock IMediator
那里有一些模拟库:
- 起订量
- FakeItEasy
- N替换
Moq 是最受欢迎的之一,因此,以您的测试为例:
[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>()));
}
为了扩展已接受的答案,如果您绝对需要使用 MediatR 测试两个服务之间的交互,您始终可以使用回调对每个 publish/handler 对进行最小起订:
_mediator = new Mock<IMediator>();
_mediator.Setup(m => m.Publish(It.IsAny<YourNotification>(), It.IsAny<CancellationToken>()))
.Callback<YourNotification, CancellationToken>((notification, cToken) =>
_yourHandlerService.Handle(notification, cToken));
上面的代码,基本上是说如果 _mediator 通过 Publish
方法获得 YourNotification
,那么它将通过 Handle
方法将它转发给 _yourHandlerService
。您可以为要处理的每种类型的调解器 INotification
重复 Setup
。