我正在将一个简单的项目更多地作为TDD的一项工作,而不是其他任何事情。该程序从Web服务器获取一些图像并将其另存为文件。记录下来,我正在做的事情(我想要的最终结果)与该Perl脚本非常相似,但使用的是C#。
我已经到了需要将文件保存到磁盘的地步。我需要进行单元测试以强制执行代码。我不确定该如何处理。我希望能够验证代码是否使用期望的文件名创建了期望的文件,并且我当然根本不想接触文件系统。我对单元测试和TDD并不完全陌生,但是由于某种原因,我真的不清楚在这种情况下该怎么做。我确定一旦看到答案,答案就会很明显,但是..我大脑中代码起源的神秘地方却没有合作。
我选择的工具是MSpec和FakeItEasy,但将不胜感激地接受任何框架中的建议。对文件系统交互进行单元测试的明智方法是什么?
在这里有帮助的是依赖注入。将整体下载操作分成较小的部分,然后将其注入到下载器中。声明这些部分的接口:
public interface IImageFetcher
{
IEnumerable<Image> FetchImages(string address);
}
public interface IImagePersistor
{
void StoreImage(Image image, string path);
}
使用这些声明,您可以编写一个downloader类,该类将整个事情集成如下:
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);
...
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句