首页 > 解决方案 > 如何在测试中模拟 FluentValidation ValidationResults

问题描述

这是我要测试的方法:

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<CreateExpenseCommand> _validator;并通过构造函数注入使用。

我正在使用 AutoFixture 和 AutoMoqCustomizations 和 Moq 进行模拟。也许我应该专门使用起订量?

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

[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-coremockingfluentvalidation

解决方案


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

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

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

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


推荐阅读