簡體   English   中英

預期對模擬的調用恰好 5 次,但正確模擬為 0 次 arguments

[英]Expected invocation on the mock exactly 5 times, but was 0 times with properly mocked arguments

通過閱讀這篇文章這篇文章,我了解到應該使用Mock並且應該等待結果。

盡管如此,我仍然得到以下異常:

Moq.MockException:預期對模擬的調用恰好 5 次,但為 0 次:_ => _.SendAsync(Mock<IClientProxy:2>.Object, It.IsAny<string>(), It.IsAny<List<Notification>>(), CancellationToken)

執行的調用:

MockIClientContextCommand:2 (_):

IClientContextCommand.SendAsync(MockIClientProxy:2.Object, "FooBarNotifications", [Notification], CancellationToken) IClientContextCommand.SendAsync(MockIClientProxy:2.Object, "FooBarNotifications", [Notification], CancellationToken) IClientContextCommand.SendAsync(MockIClientProxy:2.Object, "FooBarNotifications", [Notification ], CancellationToken) IClientContextCommand.SendAsync(MockIClientProxy:2.Object, "FooBarNotifications", [Notification], CancellationToken) IClientContextCommand.SendAsync(MockIClientProxy:2.Object, "FooBarNotifications", [Notification], CancellationToken) IClientContextCommand.SendAsync(MockIClientProxy:2.Object, "FooBarNotifications ", [通知], CancellationToken) IClientContextCommand.SendAsync(MockIClientProxy:2.Object, "FooBarNotifications", [通知], CancellationToken) IClientContextCommand.SendAsync(MockIClientProxy:2.Object, "FooBarNotifications", [通知], CancellationToken) IClientContextCommand.SendAsync(MockIClientProxy:2.Object,“FooBarNotifications”,[通知],CancellationToken)

堆棧跟蹤:Mock.Verify(Mock mock, LambdaExpression expression, Times times, String failMessage)line337 Mock 1.Verify[TResult](Expression 1 expression, Times times)line34 FooBarServiceTests.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調用。 一旦您獲得模擬以匹配預期的調用,這可能需要進一步調查。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM