Rhino Mocks: минимальное время для звонка, похоже, не работает

Я использую Rhino-Mocks 3.6 в качестве фреймворка для имитации в своих модульных тестах, и у меня проблема с Repeat.Times():

Я хочу убедиться, что метод моего имитируемого объекта вызывается ровно три раза. Согласно документации, я должен использовать Repeat.Times(3) или Repeat.Times(3, 3).

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

Вот мой код. Что-то не так?

        MockRepository mocks = new MockRepository();
        IJobServiceEvent mockedJSE;
        using (mocks.Record())
        {
            mockedJSE = mocks.DynamicMock<IJobServiceEvent>();
            Expect.Call(() => mockedJSE.TransactionListChanged(null))
                .Repeat.Times(3);
        }

        using (mocks.Playback())
        {
            mockedJSE.TransactionListChanged(null);
            mockedJSE.TransactionListChanged(null);
            mockedJSE.TransactionListChanged(null);
            mockedJSE.TransactionListChanged(null);
        }

person Jan    schedule 09.02.2011    source источник


Ответы (1)


Вам нужно использовать StrictMock. DynamicMock разрешает вызовы методов, которые не ожидаются. Таким образом, ваш вызов метода ожидается три раза (что и происходит). Но когда это происходит в четвертый раз, это не ошибка, поскольку вы определили его как DynamicMock (разрешены неожиданные вызовы).

Однако в конечном итоге использование StrickMock может стать головной болью при обслуживании, поскольку ваш тест слишком много знает о том, как написан объект (поскольку вам нужно имитировать / заглушать каждый возможный вызов, который может быть сделан).

Я бы порекомендовал синтаксис AAA (Arrange, Act, Assert) для ваших модульных тестов. Ваш тест, приведенный выше, может быть написан с использованием заглушки, но все же принудительно использовать трехлимитный вызов для вашего метода:

IJobServiceEvent mockedJSE = MockRepository.GenerateStub<IJobServiceEvent>();

mockedJSE.TransactionListChanged(null);
mockedJSE.TransactionListChanged(null);
mockedJSE.TransactionListChanged(null);
mockedJSE.TransactionListChanged(null);

mockedJSE.AssertWasCalled(s => s.TransactionListChanged(null), o => o.Repeat.Times(3, 3));

ОБНОВЛЕНИЕ

Чтобы убедиться, что были сделаны только вызовы с определенными аргументами (хотя я действительно думаю, что это в основном строгий имитатор, который может стать головной болью при обслуживании), используйте параметр ограничения аргументов три раза, чтобы убедиться, что эти вызовы сделаны. Затем создайте последний «AssertWasCalled», который игнорирует аргументы и убедитесь, что он был вызван только три раза:

mockedJSE.AssertWasCalled(s => s.TransactionListChanged(null), o => o.IgnoreArguments().Repeat.Times(3, 3));
person PatrickSteele    schedule 10.02.2011
comment
Хорошо, кроме того, я хочу проверить два вызова одного и того же метода с разными параметрами. Я могу заставить это работать, используя Contraints () и дважды вызывая AssertWasCalled. Но как мне проверить в этом сценарии, что не происходит третьего вызова с любой другой комбинацией параметров? Должен ли я использовать здесь строгий макет? - person Jan; 11.02.2011
comment
Смотрите мое обновление. Это должно сработать для того, что вы ищете. - person PatrickSteele; 11.02.2011