【问题标题】:How to mock FluentValidation ValidationResults in test如何在测试中模拟 FluentValidation ValidationResults
【发布时间】:2021-08-01 11:30:04
【问题描述】:

这是我要测试的方法:

public async Task<object> CreateExpense(CreateExpenseCommand command)
{
    var validationResults = await _validator.ValidateAsync(command);
    if (!validationResults.IsValid)
    {
        return validationResults.Errors.First().ToString();
    }
    //more code that is irrelevant for this post
}

为了测试这一点,我需要模拟_validatior,它被定义为private readonly IValidator&lt;CreateExpenseCommand&gt; _validator;,并通过构造函数注入来使用。

我正在使用带有 AutoMoqCustomizations 和 Moq 的 AutoFixture 进行模拟。也许我应该只使用起订量?

这是我在测试中尝试做的:

[Fact]
public async Task CreateExpense_Success()
{
    //Arrange
    var service = _fixture.Fixture.Freeze<Mock<IValidator<CreateExpenseCommand>>>();
    service.Setup(x => x.Validate((CreateExpenseCommand)It.IsAny<IValidator<CreateExpenseCommand>>())).Returns(It.IsAny<ValidationResult>);
    
    //more code that is irrelevant for this post
}

但是,这会导致错误:

System.NullReferenceException: '对象引用未设置为对象的实例'。

错误是不言自明的,但我不知道如何正确模拟。

错误图片:

【问题讨论】:

    标签: c# .net-core mocking fluentvalidation


    【解决方案1】:

    设置时需要返回一个对象:

    service.Setup(x => x.Validate(It.IsAny<IValidator<CreateExpenseCommand>>()))
        .Returns(<*1>);
    

    *1 - 此处返回您在调用ValidateAsync 函数时希望返回的对象。不要做It.IsAny,因为它返回null,这会导致NullReferenceException

    另外,您需要将virtual 添加到ValidateAsync 方法中以使其可被覆盖。

    【讨论】:

    • 谢谢米莎。我制作了一个验证结果,设置返回。但是,由于我在实际代码中使用ValidateAsync,因此我需要使用它而不是模拟测试中Validate 发生的情况。但是当我更改为ValidateAsyncReturnsAsync 时,它给了我错误:an expression tree may not contain a call or invocation that uses optional arguments. 任何想法?
    • 我想通了。我将添加一个更详细的答案。感谢您的贡献,它帮助我终于维持生计。
    猜你喜欢
    • 1970-01-01
    • 2018-10-20
    • 2020-07-17
    • 2023-03-20
    • 2017-05-16
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    相关资源
    最近更新 更多