Код модульного тестирования с зависимостью файловой системы - PullRequest
123 голосов
/ 24 сентября 2008

Я пишу компонент, который, учитывая ZIP-файл, должен:

  1. Распакуйте файл.
  2. Найдите конкретную dll среди разархивированных файлов.
  3. Загрузите эту dll через отражение и вызовите для нее метод.

Я бы хотел провести модульное тестирование этого компонента.

Я испытываю желание написать код, который имеет непосредственное отношение к файловой системе:

void DoIt()
{
   Zip.Unzip(theZipFile, "C:\\foo\\Unzipped");
   System.IO.File myDll = File.Open("C:\\foo\\Unzipped\\SuperSecret.bar");
   myDll.InvokeSomeSpecialMethod();
}

Но люди часто говорят: «Не пишите модульные тесты, основанные на файловой системе, базе данных, сети и т. Д.»

Если бы я написал это дружественным для юнит-теста способом, я бы предположил, что это выглядело бы так:

void DoIt(IZipper zipper, IFileSystem fileSystem, IDllRunner runner)
{
   string path = zipper.Unzip(theZipFile);
   IFakeFile file = fileSystem.Open(path);
   runner.Run(file);
}

Ура! Теперь это можно проверить; Я могу кормить в тестовых двойниках (mocks) к методу DoIt. Но какой ценой? Теперь мне нужно было определить 3 новых интерфейса, чтобы сделать это тестируемым. И что именно я тестирую? Я проверяю, что моя функция DoIt правильно взаимодействует со своими зависимостями. Это не проверяет, что zip-файл был разархивирован и т. Д.

Не похоже, что я больше тестирую функциональность. Такое ощущение, что я просто тестирую взаимодействия в классе.

У меня такой вопрос : как правильно провести модульное тестирование того, что зависит от файловой системы?

edit Я использую .NET, но концепция может также применять Java или нативный код.

Ответы [ 11 ]

0 голосов
/ 16 декабря 2008

Как уже говорили другие, первое прекрасно подходит как интеграционный тест. Вторая проверяет только то, что функция должна делать на самом деле, и это все, что должен делать модульный тест.

Как показано, второй пример выглядит немного бессмысленным, но он дает вам возможность проверить, как функция реагирует на ошибки на любом из шагов. В этом примере у вас нет проверки ошибок, но в реальной системе это может произойти, и внедрение зависимостей позволит вам протестировать все ответы на любые ошибки. Тогда стоимость того стоила.

...