使用文件IO的单元测试方法

rup*_*nan 10 c# tdd nunit unit-testing mocking

我正在努力养成编写单元测试的习惯,之前我写了一些,但它们通常都很基础......我想开始转向TDD,因为我想提高质量我的代码(设计和结构) - 减少耦合,同时希望减少回归到可测试构建的回归数量.

我采取了一个相对简单的项目,我开始工作.生成的程序监视文件夹,然后对该文件夹中的文件执行操作.

以下是从项目中提取的一些代码的典型示例:

private string RestoreExtension(String file)
    {
        var unknownFile = Path.GetFileName(file);
        var ignoreDir = Path.GetDirectoryName(file) + "\\Unknown";
        string newFile;

        //We need this library for determining mime
        if (CheckLibrary("urlmon.dll"))
        {
            AddLogLine("Attempting to restore file extension");
            var mime = GetMimeType(BufferFile(file, 256));
            var extension = FileExtensions.FindExtension(mime);
            if (!String.IsNullOrEmpty(extension))
            {
                AddLogLine("Found extension: " + extension);
                newFile = file + "." + extension;
                File.Move(file, newFile);
                return newFile;
            }
        }
        else
        {
            AddLogLine("Unable to load urlmon.dll");
        }

        AddLogLine("Unable to restore file extension");

        if (!Directory.Exists(ignoreDir))
        {
            Directory.CreateDirectory(ignoreDir);
        }
        var time = DateTime.Now;
        const string format = "dd-MM-yyyy HH-mm-ss";

        newFile = ignoreDir + "\\" + unknownFile + "-" + time.ToString(format);
        File.Move(file, newFile);

        return String.Empty;
    }
Run Code Online (Sandbox Code Playgroud)

问题:

如何使用IO测试方法?我真的不想使用真正的文件,因为这会很慢(更多的是集成测试?),但我真的看不到另一种方式.我可以添加一个可切换的IO抽象层,但这听起来像是它可能会不必要地使代码复杂化......

这样的项目值得单元测试吗?我的意思是,它太简单了.一旦你删除了.Net和第三方库调用,就没有多少了......那么,使其成为可测试的工作量意味着它不适合测试吗?

这个项目中的很多方法都是私有的,因为这个项目碰巧是一个Windows服务.我读过你应该只测试外部可见的方法(公共或通过接口公开),但在这种情况下我不太可能想要公开我自己的任何方法.那么这个项目是否值得测试(因为id可能需要将方法访问修饰符更改为public或添加一些属性以便NUnit可以看到它们)?

干杯

nei*_*in. 9

关于如何测试文件I/O:执行此操作的常用方法是将文件I/O封装在包装类中.例如:

public class FileHandler : IFileHandler
{
     public string GetFilename(string name)
     {
         return System.IO.GetFileName(name);
     }

    public string GetDirectoryName(string directory)
    {
         return System.IO.GetDirectoryName(directory);
    }
}

public interface IFileHandler
{
      string GetFilename(string name);
      string GetDirectoryName(string directory);
}
Run Code Online (Sandbox Code Playgroud)

在您测试的方法中,您只对该接口进行编程.运行单元测试时,您将使用返回预定义值的模拟对象.为此,您可以使用Moq.

这有点工作要做,但是你也不需要测试文件I/O.

最佳Jan


k.m*_*k.m 6

如何使用IO测试方法?

通过在.NET的IO库中引入抽象,然后在应用程序中使用实际实现(BCL),在单元测试中使用伪(模拟).这样的抽象很容易自己编写,但是那些项目已经存在(例如System.IO.Abstraction),所以重新发明轮子毫无意义,特别是在如此微不足道的事情中.

我真的不想使用真正的文件,因为这会很慢

这是正确的,在测试中你想使用(模拟)对象.

这样的项目值得单元测试吗?

每个项目都值得测试,您将以某种方式对其进行测试(在最极端的情况下,通过手动执行应用程序并进行良好的旧点击等待测试).

请注意,手动测试复杂解析器方法的10个边缘情况几乎总是耗费时间,每次都需要加载大文件并等待结果.这是隔离环境中的自动化测试极大地帮助的地方.它与您的代码相同 - 文件系统,Web服务,它们都会在您获得实际业务逻辑之前引入大量开销.必须孤立.

这个项目中的很多方法都是私有的(...)我读过你应该只测试外部可见的方法

再次纠正,你应该测试公共合同.但是,如果私有东西变得足够大,可以测试它,大多数情况下它是一个很好的指标,它也足够大,可以把它放在自己的类中.请注意,仅为单元测试使用更改成员访问修饰符不是最好的主意.提取类/方法重构几乎总是更好.