小编Jac*_*ams的帖子

调用静态方法的单元测试方法的模式或实践

最近,我一直在思考"模拟"从我试图测试的类中调用的静态方法的最佳方法.以下面的代码为例:

using (FileStream fStream = File.Create(@"C:\test.txt"))
{
    string text = MyUtilities.GetFormattedText("hello world");
    MyUtilities.WriteTextToFile(text, fStream);
}
Run Code Online (Sandbox Code Playgroud)

我知道这是一个相当糟糕的例子,但它有三个静态方法调用,它们略有不同.File.Create函数访问文件系统,我没有该函数.MyUtilities.GetFormattedText是我拥有的一个函数,它纯粹是无状态的.最后,MyUtilities.WriteTextToFile是我拥有的一个函数,它访问文件系统.

我最近一直在思考的是,如果这是遗留代码,我怎么能重构它以使它更可单元测试.我听过几个不应该使用静态函数的论点,因为它们很难测试.我不同意这个想法,因为静态函数是有用的,我不认为应该丢弃一个有用的工具只是因为正在使用的测试框架无法很好地处理它.

经过大量的搜索和审议,我得出的结论是,基本上可以使用4种模式或实践来使函数调用静态函数可单元测试.这些包括以下内容:

  1. 根本不要模拟静态函数,只需让单元测试它.
  2. 将静态方法包装在实例类中,该实例类使用您需要的函数实现接口,然后使用依赖注入在类中使用它.我将其称为接口依赖注入.
  3. 使用Moles(或TypeMock)来劫持函数调用.
  4. 对函数使用依赖注入.我将其称为函数依赖注入.

我听过很多关于前三种做法的讨论,但是当我在考虑这个问题的解决方案时,我想到了函数依赖注入的第四个想法.这类似于在接口后面隐藏静态函数,但实际上不需要创建接口和包装类.这方面的一个例子如下:

public class MyInstanceClass
{
    private Action<string, FileStream> writeFunction = delegate { };

    public MyInstanceClass(Action<string, FileStream> functionDependency)
    {
        writeFunction = functionDependency;
    }

    public void DoSomething2()
    {
        using (FileStream fStream = File.Create(@"C:\test.txt"))
        {
            string text = MyUtilities.GetFormattedText("hello world");
            writeFunction(text, fStream);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有时,为静态函数调用创建接口和包装类可能很麻烦,并且它可能会污染您的解决方案,其中许多小类的唯一目的是调用静态函数.我只是编写易于测试的代码,但这种做法似乎是一个糟糕的测试框架的解决方法.

当我考虑这些不同的解决方案时,我开始理解上面提到的所有4种做法都可以应用于不同的情况.以下是我认为应用上述实践正确条件 …

c# static unit-testing function mocking

34
推荐指数
2
解决办法
2万
查看次数

标签 统计

c# ×1

function ×1

mocking ×1

static ×1

unit-testing ×1