Эквивалент NSubstitute VerifyAll

Есть ли в NSubstitute аналог вызова VerifyAll MOQ? Я хотел бы убедиться, что все вызовы, которые я ожидаю получить от всех заменителей, действительно вызываются, в идеале в одном методе TearDown. В настоящее время я проверяю каждый полученный вызов индивидуально в тестах, что не идеально. Во-первых, любые вызовы, которые установлены на замене, но которые затем фактически не вызываются, будут проскальзывать через сеть, если они не были явно проверены индивидуально.


person levelnis    schedule 07.02.2013    source источник
comment
Как указано в нескольких ответах, NSub на самом деле не предназначен для поддержки этого. Если вы действительно заинтересованы, очень неуклюжий способ воспроизвести это — использовать ReceivedCalls(): groups.google.com/group/nsubstitute/browse_frm/thread/ Если вам это нужно часто, вам, вероятно, лучше всего придерживаться Moq или Rhino Mocks.   -  person David Tchepak    schedule 07.02.2013


Ответы (3)


NSubstitute предназначен для тестов в стиле AAA, а не для записи/воспроизведения. Таким образом, он их не поддерживает.

person Daniel Hilgarth    schedule 07.02.2013
comment
Я использую его в стиле ААА. Даже следуя этому стилю, полезно иметь возможность проверять все методы, которые, как вы ожидаете, будут вызываться на вашем заменителе, без необходимости явно проверять каждый из них. Если вы забудете подтвердить один из них, это немного разбавит смысл теста. - person levelnis; 07.02.2013
comment
@levelnis: Только в записи/воспроизведении вы должны явно указать все методы, которые будут вызываться вашим SUT. В AAA вам не нужно этого делать, поэтому VerifyAll не может работать. - person Daniel Hilgarth; 07.02.2013
comment
Конечно, вам не обязательно это делать, но вы не сможете проверить все вызовы, в том числе те, которые вы настроили, но забыли удалить позже в результате рефакторинга или чего-то еще, или потому что вы не так усердно очищая ваши вызовы ожиданий, как следовало бы, можно написать проходные тесты с вызовами методов, которые отслеживаются заменой, но на самом деле не вызываются. Я бы сказал, что эти тесты должны провалиться. В идеальном мире мы все были бы достаточно усердны, чтобы отрицать это, но эта всеобъемлющая проверка помогла бы в этом. - person levelnis; 07.02.2013
comment
@levelnis: Вы спросили, возможно ли это с NSubstitute: это не так. Во-вторых, я не понимаю, почему тест должен провалиться, потому что метод был настроен на замену, а ТУС не вызывает этот метод. Если этот метод не подходит для вашего теста, нет никаких причин для его неудачи. С другой стороны, если этот метод актуален, вы будете явно проверять его, и тест не будет неудачным, если вы рефакторите ТУС, чтобы не вызывать его, но забыли настроить тест. - person Daniel Hilgarth; 07.02.2013
comment
Это справедливо, Дэниел. Я беспокоюсь только о том, чтобы тестовый код был как можно более компактным, гарантируя, что в нем нет ничего лишнего. Мне просто нужно привыкнуть думать о построении тестов немного по-другому. Спасибо за ваш вклад - person levelnis; 07.02.2013
comment
@levelnis: Лин-тесты — это хорошо. Но еще важнее коммуникативные тесты. Как вы думаете, что лучше передает ожидаемое: substitute.VerifyAll() или substitute.Received.Foo(42)? - person Daniel Hilgarth; 07.02.2013

То, что вы описываете, - это поведение Strict mock. Строгие макеты по определению разрешают только то, что вы явно настраиваете и ожидаете. Это создает очень хрупкие тесты, которые имеют тенденцию очень часто ломаться по мере изменения вашего кода, поэтому использование строгих макетов не рекомендуется и вообще не поддерживается более новыми фреймворками, такими как NSubstitute или FakeItEasy.

Я бы предложил просто создать два теста для каждого из методов, которые вам нужно проверить: тест, который проверяет, что определенный метод был вызван, а затем другой, который в том же сценарии проверяет этот другой метод < strong>не был вызван. Таким образом, в случае, если ваша логика изменится, и один из методов будет вызван/не вызван, когда он должен, вы получите только один тест.

person Igal Tabachnik    schedule 07.02.2013
comment
Это создает очень хрупкие тесты, которые имеют тенденцию очень часто ломаться по мере изменения вашего кода... означает, что строгие макеты делают свою работу! Они призывают вас упростить взаимодействие между объектами, что со временем повышает стабильность. Они делают это, выделяя излишне сложные взаимодействия, которые делают тесты хрупкими и так далее. - person J. B. Rainsberger; 07.02.2013
comment
С уважением не соглашусь. Если вы следуете традиционному пути TDD, вам не нужно полагаться на универсальную функцию для обнаружения изменений потока, вы скорее добавляете новые тесты, которые проверяют новые взаимодействия. Если вы добавляете новый условный вызов, например, и один из ранее написанных вами тестов сломался из-за него, вы можете исправить это, добавив новую логику условия. Представьте, что все тесты постоянно терпели неудачу после добавления еще одного вызова. Вот почему они называются хрупкими, так как они потенциально могут сломаться после простого изменения, о котором вы, возможно, не заботитесь. - person Igal Tabachnik; 07.02.2013
comment
Я не понимаю, как ваш комментарий связан с моим комментарием. Я не полагаюсь на универсальную функцию, как вы описываете. Я часто исправляю ненадежные тесты, упрощая взаимодействие в производственном коде вместо того, чтобы делать макеты менее строгими. Я вижу в этом преимущество строгих насмешек. Это моя точка зрения. Что касается следования традиционному пути TDD, то да. Я помог популяризировать традиционный метод TDD. :) - person J. B. Rainsberger; 28.10.2013

Я знаю, что это довольно старо, и я не уверен, на чью сторону я попадаю в Loose vs Strict, но для NSubstitute вы можете добиться этого следующим образом (стиль xUnit):

Assert.Empty(_logger.ReceivedCalls());

Он показывает вам все полученные звонки, которые есть у конкретного макета, поэтому вы можете просто убедиться, что это число равно 0. Это может быть более новая функция, чем раньше, но мы хотели убедиться, что она есть! :)

person Daniel Lorenz    schedule 26.01.2018