通过阅读这篇文章和这篇文章,我明白应该使用Mock
,并且应该等待结果。
然而,我仍然得到以下异常:
Moq。MockException:对mock的预期调用正好5次,而是0次:_ =>
_.SendAsync(Mock<IClientProxy:2>.Object, It.IsAny<string>(), It.IsAny<List<Notification>>(), CancellationToken)
执行调用:
MockIClientContextCommand: 2 (_):
IClientContextCommand.SendAsync (MockIClientProxy: 2。对象,FooBarNotifications", [Notification], CancellationToken)IClientContextCommand.SendAsync (MockIClientProxy: 2。对象,FooBarNotifications", [Notification], CancellationToken)IClientContextCommand.SendAsync (MockIClientProxy: 2。对象,FooBarNotifications", [Notification], CancellationToken)IClientContextCommand.SendAsync (MockIClientProxy: 2。对象,FooBarNotifications", [Notification], CancellationToken)IClientContextCommand.SendAsync (MockIClientProxy: 2。对象,FooBarNotifications", [Notification], CancellationToken)IClientContextCommand.SendAsync (MockIClientProxy: 2。对象,FooBarNotifications", [Notification], CancellationToken)IClientContextCommand.SendAsync (MockIClientProxy: 2。对象,FooBarNotifications", [Notification], CancellationToken)IClientContextCommand.SendAsync (MockIClientProxy: 2。对象,FooBarNotifications", [Notification], CancellationToken)IClientContextCommand.SendAsync (MockIClientProxy: 2。对象,FooBarNotifications", [Notification], CancellationToken)IClientContextCommand.SendAsync (MockIClientProxy: 2。Object, "FooBarNotifications" [Notification], CancellationToken)
Stack Trace: Mock。验证(Mock Mock, LambdaExpression表达式,Times Times, String failMessage)line337模拟
1.Verify[TResult](Expression
1表达式,Times Times)line34FooBarServiceTests.SendAsync_ShouldBe_Called_N_Times () line105
所以单元测试是这样的:
private readonly Mock<IClientContextCommand> _mockClientContextCommand;
// constructor
public FooTests()
{
_mockClientContextCommand = new Mock<IClientContextCommand>();
_mockClientContextCommand.Setup(x =>
x.SendAsync(_mockClientProxy.Object, It.IsAny<string>(),
It.IsAny<Notification[]>(), CancellationToken.None));
services.AddSingleton(_mockClientContextCommand.Object);
}
[Fact]
public async Task SendAsync_ShouldBe_Called_N_Times()
{
await _hostedService.StartAsync(CancellationToken.None);
await Task.Delay(1);
await _hostedService.StopAsync(CancellationToken.None);
int times = GetNotifications().Count();
_mockClientContextCommand.Verify(
_ => _.SendAsync(_mockClientProxy.Object, It.IsAny<string>(),
It.IsAny<List<Notification>>(), CancellationToken.None),
Times.Exactly(times));
}
原始方法是这样的:
private async Task Send(CancellationToken stoppingToken)
{
// ... the other code is omitted for the brevity
foreach (IGrouping<string, Notification> group in messages.GroupBy(m => m.To))
{
IClientProxy connection = _hubContext.Clients.User(group.Key);
List<Notification> notifies = group.ToList();
await _clientContextCommand.SendAsync(connection,
"FooBarNotifications", notifies, stoppingToken);
}
}
接口方法如下:
public interface IClientContextCommand
{
Task SendAsync(IClientProxy clientProxy, string method,
object? arg1, CancellationToken cancellationToken = default);
}
有谁知道哪里做错了吗?如有任何帮助,不胜感激
首先,您需要使用It.IsAny
松开模拟成员的匹配参数,以便调用模拟成员。由于您的设置/验证与实际调用的不匹配,您得到测试失败。
接下来,因为这是一个似乎没有返回值的异步成员,所以该成员需要返回一个已完成的任务,以允许异步代码完成。
//... omitted for brevity
_mockClientContextCommand
.Setup(_ => _.SendAsync(It.IsAny<IClientProxy>(), It.IsAny<string>(), It.IsAny<Notification[]>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
//... omitted for brevity
int times = GetNotifications().Count();
_mockClientContextCommand.Verify(
_ => _.SendAsync(It.IsAny<IClientProxy>(), It.IsAny<string>(), It.IsAny<Notification[]>(), It.IsAny<CancellationToken>()),
Times.Exactly(times));
堆栈跟踪还显示预期计数应该是5,但显示了10次SendAsync
调用。一旦模拟与预期的调用匹配,可能需要进一步研究这一点。