ここで役立つのは依存性注入です。モノリシックなダウンロード操作を小さな断片に分割し、ダウンローダに挿入します。これらの部分のインターフェイスを宣言します。
public interface IImageFetcher
{
IEnumerable<Image> FetchImages(string address);
}
public interface IImagePersistor
{
void StoreImage(Image image, string path);
}
これらの宣言を使用すると、次のようにすべてを統合するダウンローダー クラスを作成できます。
public class ImageDownloader
{
private IImageFetcher _imageFetcher;
private IImagePersistor _imagePersistor;
// Constructor injection of components
public ImageDownloader(IImageFetcher imageFetcher, IImagePersistor imagePersistor)
{
_imageFetcher = imageFetcher;
_imagePersistor = imagePersistor;
}
public void Download(string source, string destination)
{
var images = _imageFetcher.FetchImages(source);
int i = 1;
foreach (Image img in images) {
string path = Path.Combine(destination, "Image" + i.ToString("000"));
_imagePersistor.StoreImage(img, path);
i++;
}
}
}
ImageDownloader
は、どの実装が使用され、どのように機能するかを知らないことに注意してください。
List<string>
これで、ファイル システムに格納される実際のファイル名を提供する代わりに、たとえばファイル名をファイル名に格納するダミーの永続化プログラムをテスト時に提供できるようになりました。
アップデート
// For testing purposes only.
class DummyImagePersistor
{
public readonly List<string> Filenames = new List<string>();
public void StoreImage(Image image, string path)
{
Filenames.Add(path);
}
}
テスト:
var persistor = new DummyImagePersistor();
var sut = new ImageDownloader(new ImageFetcher(), persistor);
sut.Download("http://myimages.com/images", "C:\Destination");
Assert.AreEqual(10, persistor.Filenames.Count);
...