我如何(或我)单元测试具体依赖

时间:2011-07-24 18:42:25

标签: c# unit-testing dependency-injection

我有一个业务层类,它使用System.IO.File从各种文件中读取信息。为了对这个类进行单元测试,我选择用注入的依赖替换File类的依赖,如下所示:

using System.IO;

public interface IFileWrapper
{
    bool FileExists( string pathToFile );
    Stream Open( string pathToFile );
}

现在我可以使用Mock来测试我的课程,所有这些都适合全世界。另外,我需要一个具体的实现。我有以下内容:

using System;
using System.IO;

public class FileWrapper : IFileWrapper
{
    public bool FileExists( string pathToFile )
    {
        return File.Exists( pathToFile );
    }

    public Stream Open( string pathToFile )
    {
        return File.Open( pathToFile, FileMode.Open, FileAccess.Read, FileShare.Read );
    }
}

现在我的业务类不再依赖于System.IO.File类,可以使用Mock of IFileWrapper进行测试。我认为没有必要测试System.IO.File类,因为我认为它已经过Microsoft的全面测试,并在无数次使用中得到证明。

如何测试具体的FileWrapper类?虽然这是一个简单的类(低风险),但我有更大的例子遵循相同的方法。如果不完成此操作,我无法接近100%的代码覆盖率(假设这很重要)。

我想这是一个更大的问题,如何弥合单元测试和集成测试之间的差距?是否有必要测试这个类,或者是否有一些属性来装饰这个类以从代码覆盖率计算中排除它。

3 个答案:

答案 0 :(得分:7)

根据经验,您应该对您编写的所有生产代码进行单元测试。但是,由于.NET的设计特性,总会有类似上面Adapter类的类无法正确进行单元测试。

我个人的经验法则是,如果您可以将适配器中的每个成员减少到cyclomatic complexity为1,则可以将其声明为Humble Object

AFAIK没有办法从覆盖率报告中排除代码,但您可以在单独的程序集中实现您的Humble对象,这些程序集免于覆盖率报告。

答案 1 :(得分:1)

在您的情况下,测试FileWrapper是一种开销。除了作为包装器之外,它没有任何作用。所以我会使用从覆盖率计算中排除它的属性。

在其他情况下,您可以在FileWrapper等类型的类型中使用其他逻辑,在这些情况下,Integration Testing可以为您提供帮助。

  

我想这是一个更大的问题,如何弥合之间的差距   单元测试和集成测试?

一般情况下,您应该分别使用这两种测试。集成测试应该在更高的层次上,在两个组件之间测试集成,所以如果你觉得你需要测试这个依赖 - 继续,在其他情况下不要编写这样的测试。与单元测试相比,集成测试总是更复杂,运行时间更长,维护更难,因此在编写每个集成测试之前应该三思而后行。这就是为什么我不会说如果你要为FileWrapper编写一些测试,这将是集成测试。所以我的观点是单元测试和集成测试之间没有差距,他们正在解决不同的问题。

答案 2 :(得分:0)

适配器类的唯一目的是包装文件系统。因此,您可以进行一个单元测试来检查此行为是否正确。让自己满意的包装工作正常,然后你就可以舒适地在其他任何地方使用测试双。

您的单元测试应该非常简单,但必须使用具体的实现。这意味着它可能相对较慢(> 5ms)并且有点烦人的设置/拆卸。我对单元测试的定义是运行速度相对较快且测试少量代码的定义,在本例中是一个类。

然后你必须非常小心,不要在课堂上添加任何额外的逻辑,否则逻辑也需要进行困难的单元测试。

第二种方法是在集成测试或手动测试中解决此问题。如果在任何地方使用此类,您将很快发现任何错误。由于此类的复杂性很小,因此引入错误的风险很低。