Как имитировать результаты проверки флуоресценции в тесте

#c# #.net-core #mocking #fluentvalidation

Вопрос:

Это метод, который я хочу протестировать:

 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; и используется с помощью инъекции конструктора.

Я использую автофиксацию с автоматическими настройками и Moq для насмешек. Может быть, мне следует использовать исключительно 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: «Ссылка на объект не установлена на экземпляр объекта».

Ошибка довольно понятна, но я не знаю, как правильно издеваться.

Изображение ошибки:введите описание изображения здесь

Ответ №1:

Вам нужно вернуть объект при выполнении настройки:

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

*1 — Здесь возвращает объект, который вы хотите вернуть при вызове ValidateAsync функции. Не делайте It.IsAny этого, так как он возвращает значение null, которое вызывает NullReferenceException .

Кроме того, вам нужно добавить virtual в ValidateAsync метод, чтобы он был переопределяемым.

Комментарии:

1. Спасибо тебе, Миша. Я сделал результат проверки, который возвращает настройка. Однако, поскольку я использую фактический код ValidateAsync , мне нужно использовать это вместо того, чтобы насмехаться над тем, что происходит Validate в тесте. Но когда я меняюсь на ValidateAsync и ReturnsAsync это дает мне ошибку: an expression tree may not contain a call or invocation that uses optional arguments. есть идеи?

2. Я все понял. Я добавлю ответ, который будет более подробным. Спасибо за ваш вклад, это помогло мне наконец-то свести концы с концами.