单元测试与文件系统交互的好方法是什么

本文关键字:方法 是什么 交互 文件系统 单元测试 | 更新日期: 2023-09-27 18:21:06

我正在做一个简单的项目,这比其他任何事情都更像是TDD中的一个练习。该程序从web服务器获取一些图像并将其保存为文件。顺便说一句,我正在做的事情(我想要的最终结果)与这个perl脚本非常相似,只是在C#中。

我已经到了需要将文件保存到磁盘的地步。我需要进行单元测试来强制执行代码。我不知道该怎么办。我希望能够验证代码是否使用预期的文件名创建了预期的文件,当然我根本不想接触文件系统。我对单元测试和TDD并不完全陌生,但出于某种原因,我真的不清楚在这种情况下该怎么办。我相信一旦我看到它,答案就会显而易见,但是。。。。我大脑中代码来源的神秘地方就是不合作。

我选择的工具是MSpec和FakeIseasy,但任何框架中的建议都将不胜感激。单元测试文件系统交互的合理方法是什么?

单元测试与文件系统交互的好方法是什么

依赖注入在这里会有所帮助。将单片下载操作分解为更小的部分,并将它们注入下载器。声明这些部分的接口:

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);
...