Я уверен, что многие люди не согласятся, но я думаю, что ваш метод в целом достаточно прост. Однако решающим моментом, который вам здесь не хватает, является внедрение зависимостей (также известное как инверсия управления), поэтому вместо нового Загрузчика, Конвертера и т. Д.внутри вашего метода вы должны определить интерфейсы для этих классов и «внедрить» их в конструктор вашего класса:
private Downloader downloader;
private Converter converter;
public MyClass(Downloader downloader, Converter converter)
{
this.downloader = downloader;
this.converter = converter;
//same with repository, it can't be a static class anymore
}
тогда вы просто используете эти экземпляры в своем методе:
//Write to the log that the import has started
Log.StartImport()
//Get the data in Excel sheet format
result = downloader.GetExcelFile()
//Log this step
Log.LogStep(result )
//convert the data to intern objects
result = converter.Convertdata(result);
//Log this step
Log.LogStep(result )
//write the data
result = repository.SaveData(result);
//Log this step
Log.LogStep(result )
теперь, после внесения этого изменения, в вашем тесте вы можете используйте одну из фреймворков имитации (я использую RhinoMocks), чтобы внедрить имитируемую реализацию зависимостей в ваш класс. Таким образом, вы можете просто убедиться, что в конвертере и загрузчике был вызван правильный метод, не читая ничего с диска и не разбирая электронные таблицы.
Примеры использования RhinoMocks приведены в их документации: http://ayende.com/wiki/Rhino+Mocks+Documentation.ashx
Не стесняйтесь задавать еще один вопрос, если вы застряли: )
Я нашел эту статью особенно полезной, когда решал, был ли мой код действительно lean and mean
Ваши комментарии и логгер (синглтон?) слишком шумные:
Log.StartImport();
result = new Downloader().GetExcelFile()
Log.Step(result);
result = new Converter().Convertdata(result);
Log.Step(result);
result = Repository.SaveData(result);
Log.Step(result);
И поскольку у вас есть три шага, которые должны произойти вместе, оберните их в Converter
. Используя DI, передайте в Converter
Downloader
и Repository
. Теперь вы получаете:
Log.StartConvert();
convert.ExcelToRepository(); //passed in with DI
Обратите внимание, что все результаты шага Log выполняются в соответствующих действиях.
У меня была похожая проблема, и способ ее решения заключался в том, чтобы действительно правильно взглянуть на SRP (Single Responsibility Principal).
ExcelFileReader, который может прочитать файл excel и вернуть набор List (строк)
Parser его работа заключается в разборе строк, возвращенных из ExcelFileReader, используя разделитель
Importer, который обрабатывает импорт DataSet, возвращенного из FileParser, в нужные таблицы.
Это позволяет сохранить тестируемую форму, поскольку ExcelFileReader не зависит от Parser или Importer. Это касается и парсера, так как его можно протестировать, просто передав ему TextReader.
Помогает ли это?
.Очень часто встречается класс, который делает то, что я считаю паттерном посредника.
Один из способов, который я нашел для борьбы с классами, которые должны иметь коллабораторов (а именно с этим вы сейчас столкнулись) - это Mock Unit Testing.
По сути, вы моделируете своих коллабораторов и устанавливаете ожидания, что произойдет с этими коллабораторами.
К сожалению, вы используете C#, а я не знаю никаких библиотек Mock для C#. Однако я уверен, что Google поможет вам найти библиотеку-макет.
Вместо библиотеки-макета вы можете просто реализовать или расширить классы ваших коллабораторов и переопределить и реализовать методы, которые вы ожидаете вызвать, с помощью методов, которые производят ожидаемый результат.
Как отметил Майкл, это значительно упрощает задачу, если в ваших коллабораторах есть инжекция зависимостей.