Модульное тестирование модуля, который проверяет интернет-соединение

У меня есть модуль C#, отвечающий за получение списка сетевых адаптеров, которые "подключены к Интернету" на компьютере с Windows Vista. Модуль использует " API диспетчера списка сетей" (или API NLM) для перебора всех сетевых подключений и возвращает все те, для которых значение IsConnectedToInternet равно true.

Я получил несколько предложений по реализации этого модуля в этом вопросе SO

Чтобы протестировать этот модуль, я решил написать помощник, который возвращает список подключенных к Интернету интерфейсов на основе другой логики, так что это будет своего рода "проверка реальности" для логики исходного модуля. Обратите внимание, что для помощника по тестированию я готов использовать методы обнаружения, которые могут считаться плохой практикой для производственного кода (например, полагаться на некоторый интернет-ресурс, например "Google") - в случае его отключения, блокировки нашим внутренним брандмауэром и т. Д. сравнительно легко исправить тест, в отличие от развернутой базы продуктов).

Альтернативный метод обнаружения, который я выбрал, состоял в том, чтобы попытаться соединиться с "www.google.com:80" с TcpClient. Моя проблема: если у меня есть более одного подключенного адаптера (например, беспроводной и локальной сети), метод обнаружения не срабатывает для одного из них с ошибкой "Был сделан запрос на подключение к уже подключенному разъему".

Мой вопрос в три раза:

  1. Как бы вы пошли на тестирование такого модуля в целом? Поддерживаете ли вы идею делать то же самое по-другому и сравнивать результаты, или это излишество, и я должен полагаться на системный API? Моя главная проблема заключается в том, что очень сложно предварительно сконфигурировать систему, чтобы я заранее знал, каковы ожидаемые результаты.

  2. Какую альтернативную логику вы бы предложили? Одна вещь, которая была предложена в вышеупомянутом вопросе, это взгляд на таблицу маршрутизации - как насчет того, чтобы считать каждый адаптер, имеющий запись маршрутизации с пунктом назначения 0.0.0.0, "подключенным к Интернету"? Другие предложения?

  3. Вы понимаете, почему я получаю "уже подключенную" ошибку с текущей тестовой логикой?

3 ответа

Решение

Я могу только ответить на ваш вопрос о модульном тесте.

Код, который вы тестируете, - это, по вашим словам, "модуль C#, отвечающий за получение списка сетевых адаптеров, которые" подключены к Интернету "на компьютере с Windows Vista. Модуль использует API-интерфейс Network List Manager API (или NLM API) для перебора всех сетевых подключений и возврата всех тех, для которых значение IsConnectedToInternet равно true. "

Если бы я писал этот модуль, я бы сначала использовал интерфейс для API NLM, назовите его... NLMAPIService. Теперь для реального кода создайте адаптер, который реализует NLMAPIService и адаптирует настоящий NLM API.

Для тестирования создайте класс FakeNLMAPI, который реализует NLMAPIService и хранит все свои данные в памяти где-нибудь, или в файле XML, или как угодно. Ваш модуль вызывает методы только в NLMAPIService, поэтому вам не нужно менять "реальный" код в зависимости от того, тестируете вы или нет.

Следовательно, в своем методе настройки теста вы можете создать экземпляр FakeNLMAPI и передать его в свой модуль, а в производстве создать экземпляр своего NLM API-адаптера.

Я собираюсь предположить, что вы можете создать экземпляр и изменить объект, который представляет сетевое соединение. Если нет, вы можете следовать той же схеме для подделки фактического объекта сетевого подключения.

Внедрение зависимостей - очень удобный шаблон для решения подобных проблем. Вместо простого использования компонентов API NLM непосредственно в вашем коде определите интерфейс и класс, который его реализует и служит прокси для API NLM. Передайте экземпляр этого класса в ваш модуль в конструкторе и пусть ваш модуль использует его. В ваших модульных тестах вместо реального прокси-объекта используйте фиктивный объект, который возвращает известную информацию - ему даже не нужно ссылаться на API NLM - для использования при тестировании логики вашего модуля. Конечно, ваш прокси-класс также нуждается в некотором тестировании, но логика в нем намного проще - возможно, просто маршалинг данных. Вы можете убедить себя в его правильности или, если нет, провести ручное тестирование, чтобы убедиться, что оно работает правильно.

UnitTests не должен иметь доступ к внешним ресурсам. Чтобы UnitTest ваш метод, я бы заглушил API Network List Manager.

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

Другие вопросы по тегам