#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. Я все понял. Я добавлю ответ, который будет более подробным. Спасибо за ваш вклад, это помогло мне наконец-то свести концы с концами.