无法为 MediatR 设置最小起订量回调

Cannot setup a Moq callback for MediatR

我正在编写一个测试来验证我的控制器是否使用预期的查询参数调用我的查询。这是我的查询 class:

public class GetProducts : IRequest<IEnumerable<Product>>
{
    public int CategoryId { get; set; }
}

这实现了 IRequest<T> MediatR 接口。

这是不起作用的测试用例:

[Theory]
[InlineData(1)]
public async Task GetProductsAsync_GivenValidRequestParameters_ReturnsListGetProductsResponseAsync(int categoryId)
{
    var expectedQuery = new GetProducts
    {
        CategoryId = categoryId
    };

    _mediatorMock
        .Setup(s => s.Send(It.IsAny<GetProducts>(), It.IsAny<CancellationToken>()))
        .Callback<GetProducts, CancellationToken>((query, ct) => query.Should().BeEquivalentTo(expectedQuery))
        .ReturnsAsync(Enumerable.Empty<Product>());

    var response = await _productsController.GetProductsAsync(categoryId);

    response.Result.Should().BeOfType<OkObjectResult>();
    _mediatorMock.Verify(s => s.Send(It.IsAny<GetProducts>(), It.IsAny<CancellationToken>()), Times.Once);
}

这是我正在测试的控制器:

[ApiController]
[Route("categories/{categoryId:int}/products")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[TrackUsage]
public class ProductsController : ControllerBase
{
    private readonly IMediator _mediator;

    public ProductsController(IMediator mediator)
    {
        _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<GetProductsResponse>>> GetProductsAsync([FromRoute]int categoryId)
    {
        var query = new GetProducts
        {
            CategoryId = categoryId
        };

        var products = await _mediator.Send(query);

        return Ok(products.ToResponse());
    }
}

它抱怨因为它找不到以 <GetProducts, CancellationToken> 作为参数的回调,即使它看起来是正确的。

我知道我可以使用 It.Is<...>(callback => true) 检查每一个 属性,但可能会有具有多个属性的查询,我更愿意使用 FluentAssertion 进行测试。

通用Send定义

public interface IMediator
{
    /// <summary>
    /// Asynchronously send a request to a single handler
    /// </summary>
    /// <typeparam name="TResponse">Response type</typeparam>
    /// <param name="request">Request object</param>
    /// <param name="cancellationToken">Optional cancellation token</param>
    /// <returns>A task that represents the send operation. The task result contains the handler response</returns>
    Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default);

    //...

Source

Callback 需要匹配提供的定义

//...

_mediatorMock
    .Setup(s => s.Send<IEnumerable<Product>>(It.IsAny<IRequest<IEnumerable<Product>>>(), It.IsAny<CancellationToken>()))
    .Callback<IRequest<IEnumerable<Product>>, CancellationToken>((query, ct) => 
        ((GetProducts)query).Should().BeEquivalentTo(expectedQuery)
    )
    .ReturnsAsync(Enumerable.Empty<Product>());

//...