无法对调用静态方法的方法进行单元测试,如何重新设计该程序?

时间:2018-06-26 19:09:47

标签: c# .net unit-testing oop static

我有一个可在整个程序中将日志写入文本文件的类。我认为制作方法static是一个好主意,因为它只有几种方法,并且在程序的许多不同部分中都被调用。在程序开始时会一次调用此方法以创建初始文件。

public static void CreateAuditLog()
{
    var fileName = Path.Combine(filePath, 
        $@"AuditFile{DateTime.Now:yyyy-MM-dd_hh-mm-ss-fff}.txt");

    writer = new StreamWriter(new FileStream(fileName,
        FileMode.CreateNew, FileAccess.Write));

    GetAuditLogFileSize();
}

但是,在编写单元测试时,我不知道您无法测试调用静态方法的方法。 (来自代码库的示例方法)

public Decimal CalculateCurrentBalance
{
    get
    {
        var balance = TotalAmountBilled - TotalAmountPaid;
        Audit.Message(2, $"Balance: {balance} for: {Name}");
        return TotalAmountBilled - TotalAmountPaid;
    }
}

message方法有很多细节,所以我不会在这里发布所有内容,但是基本上它需要一个数字和一条消息才能登录到文本文件。流编写器特意在CreateAuditLog()中保持打开状态,以便可以在许多不同的地方调用Message(),并将消息写入日志文件。

public static void Message(int auditLevel, string message)

我觉得我设计该程序的方式很糟糕。有人对我如何重新设计它有任何建议吗?我不确定如果不在程序中的每个其他类上创建日志记录类的实例,怎么办呢?

1 个答案:

答案 0 :(得分:5)

不要在所有其他类中创建一个实例; 注入一个。

这是单元测试的基础之一;依赖注入。类不会创建或直接访问其依赖项,而是将其传递给使用的类。在这种情况下,如果您的Log类实现了ILogger(由您组成的接口),则您的类将如下所示:

public class MyInjectedClass
{
     private readonly ILogger logger;
     public MyInjectedClass(ILogger logger)
     {
        this.logger = logger;
     }

     public void SomeMethod()
     {
        logger.Message();
     }
}

当然,现在您必须在整个地方传递ILogger的实例,这很麻烦。幸运的是,有很多像NInjectAutofac这样的库可以为您连接所有依赖项。它将需要一些重构,但是一旦完成,您只需将您的日志记录类注册为ILogger接口的单例,它将自动注入到每个具有依赖项的类中。

(如果您使用的话,MS也具有.NET Core附带的DI库)

界面可能类似于:

public interface ILogger
{
     void Message(string msg);
}