Это корректно, что тупики Насмешек Носорога и насмешки только хороши для интерфейсов, не реальных классов? Я провел немало времени, пытаясь сделать эту часть из работы кода. Я не ожидал, что заблокированные pubSubClient, чтобы всегда звонить Отправляют метод от класса. Тот метод имеет некоторые зависимости и выдает исключение.
[Test]
public void Test01()
{
PubSubMessage psm = new PubSubMessage();
var pubSubClient = MockRepository.GenerateStub<PubSubClient>();
pubSubClient.Stub(x => x.Send(psm)).IgnoreArguments().Return(null);
// actual PubSubClient Send method throws exception
// the rest of the test is skipped...
}
Однако, когда я извлек интерфейс и запустил тот же тест с IPubSubClient, это, кажется, работает как ожидалось.
Это означает, что я должен извлечь интерфейс для каждого класса, который я хочу дразнить/блокировать с Носорогом? Или я пропускаю что-то, технически или концептуально?
ОБНОВЛЕНИЕ: хорошо, кажется, что я выяснил то, что пропускала первая часть: Насмешки Носорога не могут прервать вызовы к невиртуальным методам. Так, я предполагаю, что имею или интерфейсы использования или делаю каждый метод на реальном классе виртуальным. Исправьте меня, если существует другая опция.
Ответ Брайана об использовании частичных моков неверен. Не для этого нужны частичные имитации.
Ответ Джона Эриксона в основном правильный: Rhino Mocks и Moq не могут перехватывать невиртуальные вызовы, а также не могут перехватывать статические методы или свойства. Это означает, что вы не можете подделать следующее:
DateTime.Now; // static property, can't fake static property
someClass.SomeNonVirtualMethod(); // can't fake non-virtual method
sealedClass.Foo(); // can't fake anything on sealed classes
Utilities.SomeStaticMethod(); // can't fake static methods
someList.Any(); // can't fake extension methods like Linq's .Any()
TypeMock может подделать их, как сказал Джон.
Следует отметить, что существует дополнительный фреймворк для имитации, который может перехватывать все вызовы: фреймворк Microsoft Moles . Он работает так же, как TypeMock, он использует API профилировщика .NET для перехвата вызовов.
Родинки свободны (пока). Это тоже бета. Moles работает только с инструментами Microsoft Pex . И его API явно уступает изысканному и элегантному API TypeMock.
Вы должны сделать методы виртуальными. Моки Rhino (и большинство других фреймворков изоляции) используют прокси-классы для создания заглушек / имитаций.
Если вы используете TypeMock Isolator, вы можете имитировать все, что угодно, потому что эта структура изоляции использует .NET Profiler API для создания своих «заглушек / макетов»
По сути, это правильно и в целом является хорошей практикой. Однако на самом деле он полезен только для определенного типа кодирования.
Не думайте об объектах как о вещах, которыми может манипулировать некоторая «высшая сила». Вместо этого думайте о них как об автономных «людях», которые могут отправлять сообщения друг другу. Интерфейс представляет сообщения, отправленные одним объектом.
Затем вы используете имитацию для проверки того, что были отправлены правильные сообщения, а не для предоставления поддельных реализаций зависимостей.
В идеале вы не должны создавать интерфейс, который точно соответствует существующему классу - вместо этого класс , потребляющий интерфейс, заявляет о своих потребностях в форме интерфейса.
Частичные имитации позволяют имитировать функциональность конкретного класса. См .: http://www.ayende.com/wiki/Rhino+Mocks+Partial+Mocks.ashx
Я не думаю, что есть другой способ сделать это, кроме создания каких-либо методов, которые вы хотите имитировать виртуальными. - Я считаю, что способ создания макетов конкретных классов заключается в динамическом подклассе конкретного класса, над которым создается макет, и последующем переопределении заданных методов поведением, которое вы указываете в тесте, поэтому для правильной работы требуется виртуальный метод.