Причина, по которой это не работает:
void VerifyMany(int input)
{
_myClassMock.Verify(ic => ic.DoStuffA(input), Times.Once());
_myClassMock.Verify(ic => ic.DoStuffB(input), Times.Once());
}
Это потому, что It.IsAny<int>()
(при простом вызове) возвращает 0. Таким образом, по сути, когда VerifyMany
вызывается с It.IsAny<int>()
, вы передаетеОт 0 до VerifyMany
.Что, в свою очередь, означает, что DoStuffA(0)
и DoStuffB(0)
проверены (не любое целочисленное значение, как вы, вероятно, предполагали).
Другой вызов:
_myClassMock.Verify(ic => ic.DoStuffA(It.IsAny<int>()), Times.Once());
_myClassMock.Verify(ic => ic.DoStuffB(It.IsAny<int>()), Times.Once());
Работает, потому что ic => ic.DoStuffA(It.IsAny<int>()
часть никогда не вызывается напрямую.Оно превращается в дерево выражений, и Мок только гуляет (или посещает, если хотите), это дерево выражений.Это означает, что он найдет It.IsAny<int>()
в Дереве выражений, а затем сможет проверить вызов DoStuffA
(который он также нашел в том же дереве выражений) с любым целочисленным значением.(для более подробной информации о деревьях выражений, не стесняйтесь прочитать это )
Вы можете сделать эту полуработу, создав метод, который абстрагирует вызов от Verify
и принимает выражение какИтак:
void VerifyOnce(Expression<Action<ClassMockIsBasedOn>> callToVerify)
{
_myClassMock.Verify(callToVerify, Times.Once());
}
Что позволяет вам так называть:
VerifyOnce(ic => ic.DoStuffA(It.IsAny<int>())
Вы также можете расширить пример VerifyOnce
для принятия нескольких выражений.Это позволило бы вам проверить DoStuffA
и DoStuffB
в одной строке:
void VerifyOnce(params Expression<Action<ClassMockIsBasedOn>>[] callsToVerify)
{
foreach(var callToVerify in callsToVerify)
{
_myClassMock.Verify(callToVerify, Times.Once());
}
}
Это позволило бы выполнить вызов следующим образом:
VerifyOnce(ic => ic.DoStuffA(It.IsAny<int>(),
ic => ic.DoStuffB(It.IsAny<int>());
И, конечно, вы могли бы заменитьClassMockIsBasedOn
с общим.И добавьте перегрузку, которая учитывает методы, которые возвращают значения (вместо того, чтобы быть пустыми) или принимают более одного параметра, как предложил Бретт в комментариях.