Зачем использовать It.is <> или It.IsAny <>, если бы я мог просто определить переменную?

Привет, я уже некоторое время использую moq, когда вижу этот код.

Я должен настроить возврат в одном из моих репо.

 mockIRole.Setup(r => r.GetSomething(It.IsAny<Guid>(), It.IsAny<Guid>(), 
                  It.IsAny<Guid>())).Returns(ReturnSomething);

У меня есть три параметра, и я только что видел их в одной из статей или блога в сети.

Какая польза от It.Is<> или It.IsAny<> для объекта? если бы я мог использовать Guid.NewGuid() или другие типы, тогда зачем использовать It.Is?

Извините, я не уверен, правильно ли задан мой вопрос или мне не хватает некоторых знаний в тестировании. Но, похоже, в этом нет ничего плохого.

Ответы

Ответ 1

Использование It.IsAny<>, It.Is<> или переменной все служат различным целям. Они предоставляют все более конкретные способы сопоставления параметра при настройке или проверке метода.

It.IsAny

Метод, настроенный с помощью It.IsAny<>, будет соответствовать любому параметру, заданному вами для метода. Итак, в вашем примере все следующие вызовы будут возвращать одно и то же (ReturnSomething):

role.GetSomething(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid());

Guid sameGuid = Guid.NewGuid();
role.GetSomething(sameGuid, sameGuid, sameGuid);

role.GetSomething(Guid.Empty, Guid.NewGuid(), sameGuid);

Неважно, какое значение было передано Guid.

It.Is

Конструкция It.Is<> полезна для настройки или проверки метода, позволяя вам указать функцию, которая будет соответствовать аргументу. Например:

Guid expectedGuid = ...
mockIRole.Setup(r => r.GetSomething(
                 It.Is<Guid>(g => g.ToString().StartsWith("4")), 
                 It.Is<Guid>(g => g != Guid.Empty), 
                 It.Is<Guid>(g => g == expectedGuid)))
         .Returns(ReturnSomething);

Это позволяет вам ограничить значение больше, чем любое другое значение, но позволяет вам быть снисходительным в том, что вы принимаете.

Определение переменной

Когда вы устанавливаете (или проверяете) параметр метода с помощью переменной, вы говорите, что хотите именно это значение. Метод, вызванный с другим значением, никогда не будет соответствовать вашей настройке/проверке.

Guid expectedGuids = new [] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
mockIRole.Setup(r => r.GetSomething(expectedGuids[0], expectedGuids[1], expectedGuids[2]))
         .Returns(ReturnSomething);

Теперь есть только один случай, когда GetSomething вернет ReturnSomething: когда все Guid соответствуют ожидаемым значениям, с которыми вы его настроили.

Ответ 2

Если вы посмотрите документацию по быстрому запуску для Moq

Соответствующие аргументы

// any value
mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(true);


// matching Func<int>, lazy evaluated
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true); 


// matching ranges
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true); 


// matching regex
mock.Setup(x => x.DoSomething(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo");