Какова цель Verifiable () в Moq?

125

В чем цель Verifiable()?

Если я проверю a Mockи опущу это, он все равно проверяет SetUp.

Изменить: я использовал, VerifyAll()таким образом, причину, по которой все проверяется. После перехода на проверку Verify()только мои .Verifiable() SetUps.

Castrohenge
источник

Ответы:

83

ДОБАВЛЕНИЕ: Как указано в другом ответе, цель .Verifiableсостоит в том, чтобы включить Setupв набор «отложенных Verify(...)вызовов», которые затем могут быть инициированы через mock.Verify().

Разъяснение OP дает понять, что это была цель, и единственная проблема заключалась в том, чтобы выяснить, почему она не работает, но, как подсказал @Liam, ответ действительно должен коснуться и этого: - Ключевые варианты использования, насколько я могу см. следующие:

  • поддержание СУХОСТИ между a mock.Setup()иmock.Verify
  • позволяя отключить настройку проверки от самого Verifyвызова (например, вы можете настроить его в другом вспомогательном методе)

... и возвращаясь к моему ответу, который кратко и эффективно гласит: «Будьте осторожны, поскольку обычно считается, что вышеупомянутые плюсы перевешиваются влиянием, которое достижение этих целей оказывает на удобочитаемость и ремонтопригодность тестов, которые слишком сильно опираются на такие конструкции»

ОРИГИНАЛ: обратите внимание, что, где это возможно, вместо этого следует следовать макету AAA и, следовательно, следует делать явные mock.Verify( expression )вызовы после того, как работа была сделана, а не в mock.Setup( ... ).Verifiable()паре с mock.Verify()илиmock.VerifyAll() где это возможно (кредит: @kzu ).

Рубен Бартелинк
источник
7
@EricSmith Оглядываясь назад, не думаю, что я выразился достаточно сильно. Разделение работы на объединение AAA дает гораздо больше преимуществ, чем чрезмерная концентрация на общих чертах между этапами Arrange и Assert. В 90% случаев можно кое-что извлечь из нюансов того, как вы выражаете вызовы Verify в конце, поэтому вам нужно потратить много времени на оптимизацию для этого, даже если в некоторых случаях это кажется болезненным дублированием. Один из замечаний manning.com/osherove заключается в том, что очень важно сделать тест понятным для тех, кто вмешивается в него, поэтому придерживайтесь условностей!
Рубен Бартелинк,
3
Обычно я не из тех, кто идет против общепринятой мудрости, но пока еще не уверен в преимуществах AAA против Verifyable()/ VerifyAll()во всех случаях. В моем текущем модульном тесте большое количество Setup(...)вызовов (> 30). Можно сопоставить каждый из них с эквивалентным Verify () для соответствия соглашению, но это приводит к большому дублированию кода, и его будет сложнее поддерживать и читать по мере роста количества модульных тестов. Я предполагаю, что я действительно спрашиваю, могут ли быть сделаны исключения, если существует большое количество настроек, или нужно избегать Verifiable()жесткого и быстрого правила?
Стив Чемберс
5
@SteveChambers Ключевым элементом AAA является то, что это не A * - должно быть одно действие и одно утверждение. Итак, хотя вы технически правы, говоря, что для вас это меньше кода, совпадения того, какие из ваших настроек применяются к каким (под) действиям и (под) утверждениям, неизменно становятся минным полем. Так что нет, это не сложно и быстро, но я бы сказал, что предположить, что это даже близко к 50:50, было бы очень плохим советом. (Также обратите внимание, что вам не нужно выполнять настройку, чтобы выполнить проверку, если вы не пытаетесь ввести конкретное поведение во время выполнения действия, что является еще одним элементом четких тестов)
Рубен Бартелинк,
1
@Liam И это действительно совершенно нормально , что вы по- прежнему убеждены , что это подходящий инструмент для работы - моя реальная точка только , что это с неодобрением , как общий подход к написанию тестов с издевается - то есть , несмотря на то , что он аккуратно достигает Сухость между а Setupи а Verify, может отсутствовать более высокий выигрыш, достижимый только путем ослабления ограничения DRY способом, предложенным AAA и семейством стратегий, которые настоятельно подразумевают
Рубен Бартелинк
1
@Liam Спасибо за подсказку; Я обновил свой ответ, потому что вы правы в своем изложении. В тот день, когда я отвечал на такие вопросы, я обычно хотел кратко сформулировать атомарный ответ, а затем позволить конкурирующим ответам, таким как другой, заполнить карту. В наши дни (если бы я все еще находил время, чтобы ответить на вопросы), я бы, вероятно, попытался дать более полный ответ, каким это стало в первую очередь.
Рубен Бартелинк,
54

Когда Verify()метод вызывается в конце теста, если какое-либо из ожиданий, помеченных как проверяемые, не было вызвано, возникает исключение thrown.

VerifyAll() не проверяет достоверность ожиданий.

Сувеш Пратапа
источник
не могли бы вы объяснить немного больше о том, что VerifyAll () не проверяет проверяемые ожидания?
JW
@JW Это означает, что VerifyAll проверяет все настройки, не учитывая, были ли они отмечены как проверяемые ожидания.
phoog