Подтвердить что ты не робот

Moq - Можно ли указать в настройке критерии Verify (например, Times)?

Если вам нужно установить возвращаемое значение, а также проверить, сколько раз вы вызывали это выражение, можете ли вы сделать это в одном выражении?

Из того, что я могу собрать, Moq Setup (SomeExpression).Verifiable(), вызываемый вместе с Verify(), в основном выполняет Verify (SomeExpression, Times.AtLeastOnce)? т.е. verifys, выражение было вызвано только.

Вот пример, чтобы лучше объяснить вопрос. Для интерфейса:

interface IFoo
{
    int ReturnSomething();
}

Являются ли следующие два эквивалентных блока (кроме первого, будут проверять все установки, помеченные как проверяемые)?

void Test()
{
    var mock = new Mock<IFoo>();
    mock.Setup((m) => m.ReturnSomething()).Returns(1).Verifiable();

    mock.Verify();
}

и

void Test()
{
    var mock = new Mock<IFoo>();
    mock.Setup((m) => m.ReturnSomething()).Returns(1);

    mock.Verify((m) => m.ReturnSomething(), Times.AtLeastOnce());
}

Если бы я хотел проверить количество вызовов (скажем дважды), это единственный способ, когда выражение повторяется для установки и проверки?

void Test()
{
    var mock = new Mock<IFoo>();
    mock.Setup((m) => m.ReturnSomething()).Returns(1);

    mock.Verify((m) => m.ReturnSomething(), Times.Exactly(2));
}

Мне просто не нравится называть Setup и Verify. Ну, так как это хорошая идея для AAA, перефразировать, мне не нравится повторять выражение для Setup и Verify. На данный момент я сохраняю выражение в переменной и передаю его каждому методу, но не чувствую себя таким чистым.

PS - контекст для этого - проверка теста при обновлении кеша (expirations и т.д.)

4b9b3361

Ответ 1

Чтобы ответить на первый вопрос, да, два блока эквивалентны. Оба будут терпеть неудачу при вызове .Verify, если метод mock не был вызван.

Вы не можете указать проверку перед фронтом, насколько я знаю, и если вы думаете об этом, это имеет смысл.

Это указывает поведение макета:

mock.Setup(m => m.ReturnSomething()).Returns(1);

Это проверяет поведение вызывающего абонента:

mock.Verify(m => m.ReturnSomething(), Times.AtLeastOnce());

Лично я предпочитаю, чтобы вызов проверялся индивидуально, чтобы подтвердить требуемое поведение вызывающего, .Verifiable() и .Verify() являются ярлыками, которые являются менее строгими (они просто проверяют, что метод был вызван один или несколько раз), однако, если вы знаете свой код должен только вызывать метод один раз, поместить подтверждение в конце, чтобы подтвердить его.

Я начал делать это после того, как слияние кода привело к вызову метода дважды, тест по-прежнему прошел, поскольку он был вызван хотя бы один раз, но это также означало, что что-то еще произошло несколько раз, что не должно быть!

Ответ 2

У меня есть эта проблема все время. Я использую строгие издевки, и я хочу строго указать (т.е. Использовал It.Is<>() вместо It.IsAny()), а также строго проверить (т.е. Указывая Times). Вы не можете использовать проверяемое для этого печально, потому что Moq отсутствует перегрузка Verifiable(Times).

Полное выражение вызова, включая It.Is<>(), обычно велико. Поэтому, чтобы избежать дублирования, я обычно прибегаю к следующему:

Expression<Action<MockedType>> expression = mockedTypeInstance => mockedTypeInstance.MockedMethod(It.Is<TFirstArgument>(firstArgument => <some complex statement>)/*, ...*/);
_mock.Setup(expression);

/* run the test*/

_mock.Verify(expression, Times.Once);

Не очень читаемый, но я не думаю, что есть другой способ как для строгой настройки, так и для строгой проверки.