2013-05-28 5 views
3

Существует ли стандартный метод для кода модульного тестирования, где зависимости не реализуют интерфейсы? Например, пространство имен System.Net.Http предоставляет только конкретные классы. Если я пытаюсь выполнить модульный тест класса, который опирается на один из конкретных классов в System.Net.Http, должен ли я просто построить экземпляр, скажем, HttpRequestMessage, установить его свойства и затем передать этот вновь построенный объект в тестируемую систему? Имеет ли смысл подкласс HttpRequestMessage и реализовать ли он пользовательский интерфейс, который затем можно было бы насмехаться/прорезать?Существует ли стандартный метод для кода модульного тестирования, где зависимости не реализуют интерфейсы?

+0

При тестировании с зависимостями, которые вы хотите, чтобы эти зависимости в контроле вы находитесь. Подкласс/абстрагирование необязательно требуется. То, что вы действительно хотите сделать, - это заглушить вашу зависимость и заставить ее вести себя так, как ее ожидает испытуемый. – Polity

ответ

8

Рекомендуемая практика заключается в том, чтобы обернуть этот объект в класс вашего творения, который сам реализует интерфейс. Затем вы использовали бы этот класс-оболочку в своем коде, и затем вы можете предоставить посмеянные версии этой оболочки вместо реального класса. Вы не будете подклассифицировать его с помощью этого метода, а скорее сохраните его и используйте делегирование (не путать с делегатами!) Для пересылки каждого метода.

Например, вы можете создать класс HttpRequestMessageWrapper, который наследует от IHttpRequestMessage (который вы определяете, включая все общедоступные свойства HttpRequestMessage .. хотя вы, вероятно, могли бы справиться с использованием только тех свойств, которые вы используете).

В качестве альтернативы вы можете использовать платформу тестирования, которая поддерживает прокладки, которая представляет собой инфраструктуру, которая по существу делает эту оболочку для вас и заменяет вызовы объектов с версиями прокладки. Microsoft Fakes (введенный в VS 2012 MS Test) делает это.

Прокладки обычно используются для замены обычных вызовов каркаса, таких как DateTime.Now, поэтому вы можете указать определенное значение во время тестов.

+0

Спасибо. Это имеет смысл и должно позволить мне гибко вносить изменения во внутренние действия чего-то вроде HttpRequestMessageWrapper в будущем, не нарушая никаких контрактов. –

+0

@BradfordFisher - на самом деле это не изменит внутреннюю работу класса, хотя это упростит замену определенных функций, вызываемых через интерфейс. Класс, который вы обертываете, не будет знать вашу обертку. Я бы рекомендовал не изменять поведение обернутого класса, так как это может вызвать различные непредвиденные проблемы. –

0

Я бы предложил вам взглянуть на: AutoFixture http://autofixture.codeplex.com/ Это поможет вам построить объект так, как вы хотите. В вашем примере HttpRequestMessage вы можете настроить прибор: fixture.Customize<HttpRequestMessage>(c => {}); Существует много примеров использования AutoFixture в Unit Testing. Или вы можете опубликовать код, который вы хотите проверить здесь, и я могу попытаться помочь.

+0

Autofixture не поможет большинству фреймворческих классов, так как вы должны иметь возможность заглушить функциональность. Например, как использование Autofixture поможет заглушить класс Socket? Это поможет только тем классам, которые по сути являются POCO. –

+0

Полностью согласен с вами в этом. Для всех случаев нет серебряной пули. В AutoFixture вы можете настроить фальшивую структуру, которую хотите использовать. Я согласен с вашим ответом выше, но в большинстве случаев я могу сделать unittest с AutoFixture + RhinoMock (или Moq). По крайней мере, в проектах, которые я сделал. –

+0

AutoMocking работает только с интерфейсами и абстрактными классами, суть которых заключалась в том, как тестировать класс, который использует конкретные классы, которые НЕ реализуют их. –

0

Еще один хороший инструмент для тестирования унаследованного кода Typemock

Смежные вопросы