温馨提示:本文翻译自stackoverflow.com,查看原文请点击:c# - Generic method for verifying whether a mocked method called
.net-core c# xunit moq

c# - 用于验证模拟方法是否称为通用方法

发布于 2020-04-03 23:23:58

我正在构建通用的测试助手方法,以验证是否在给定类型的模拟中调用了某个方法。在我的示例中,我IMediatorMediatR库中嘲笑为了嘲笑我正在使用Moq库

让我们看一下代码。为了简单起见,我做了一个“虚拟”服务和相应的测试,仅关注此问题。我的生产代码:

public class Service
{
    private readonly IMediator _mediator;

    public Service(IMediator mediator)
    {
        _mediator = mediator;
    }

    public void SendQuery()
    {
        _mediator.Send(new GetAllProductsQuery());
    }
}

并进行相应的测试:

    [Fact]
    public void  WhenSendQueryCalled_ThenGetAllProductsQuerySend()
    {
        //Arrange
        var mockedMediator = new Mock<IMediator>();
        var service = new Service(mockedMediator.Object);

        //Act
        service.SendQuery();

        //Assert
        CheckThatRequestSentViaMediator<GetAllProductsQuery>(mockedMediator);
    }

    private void CheckThatRequestSentViaMediator<TRequest>(Mock<IMediator> mockedMediator) where TRequest : class
    {
        mockedMediator.Verify(mock => mock.Send(It.IsAny<TRequest>(), It.IsAny<CancellationToken>()), Times.Once);
    }

我的assert方法确实由于以下原因意外失败:

Moq.MockException: 
Expected invocation on the mock once, but was 0 times: mock => mock.Send(It.IsAny<GetAllProductsQuery>(), It.IsAny<CancellationToken>())

Performed invocations:

   Mock<IMediator:1> (mock):

另一方面,如果我直接在验证方法中指定类型,则测试通过。传递的assert方法如下所示:

    private void CheckGetAllProductsQuerySentViaMediator(Mock<IMediator> mockedMediator)
    {
        mockedMediator.Verify(mock => mock.Send(It.IsAny<GetAllProductsQuery>(), It.IsAny<CancellationToken>()), Times.Once);
    }

对我来说,这很奇怪,因为第二个assert方法存在缺陷。但是,如果我使用通用类型参数并将其粘贴到verify方法上,它将失败。我究竟做错了什么?我是否不了解C#/。NET.Core的一些重要基础行为?谢谢您的帮助!

查看更多

提问者
mirind4
被浏览
27
Johnny 2020-01-31 21:30

看来问题出在您的约束上where TRequest : class

如果您查看,IMediator则会发现两种方法:

  1. 接收 IRequest<TResponse>

  2. 接收 object

moq真正弄清楚要使用哪个替代值是令人困惑的尝试对类型进行明确说明,以真正指向正确的方法,例如:

private static void CheckThatRequestSentViaMediator<T>(Mock<IMediator> mediator) 
    where T : IRequest<T>

要么

private static void CheckThatRequestSentViaMediator<T>(Mock<IMediator> mediator) where T : class
{
    mediator.Verify(mock => mock.Send(It.IsAny<IRequest<T>>(), It.IsAny<CancellationToken>()), Times.Once);
}