如何在单例类上使用Moq,以便我们只能测试业务逻辑并忽略日志记录

时间:2014-06-17 05:16:29

标签: c# .net unit-testing singleton moq

 public class SLogger
 {
     private const string SSchemasFileName = "sSchemas";
     private const string SLogsFileName = "sLogs";

     private static string logsDir = @"D:\Data\logs\local\";
     private static readonly Lazy<SLogger> instance = new Lazy<SLogger>(() => new SLogger());

     private ESC eSC;
     private AEL aEL;

     private SllLogger()
     {
         eSC= new ESC(logsDir , SSchemasFileName);
         aEL= new AEL(logsDir , SLogsFileName, EventLevel.Verbose);
     }

     public static SLogger Instance
     {
         get
         {
             return instance.Value;
         }
     }

     public void LogInformation()
     {
         // Some logic here
     }
}

如何使用Moq框架来测试业务逻辑并忽略日志库代码?

例如,如果我有一个类,其中有一个如下所示的方法,并且我想使用Moq框架或任何其他框架对此方法进行单元测试,那么我该如何对这个单例类进行Moq?

我还有其他办法吗?

void foo()
{
   // Business logic

   SLogger.Instance.LogInformation();

   // Business logic
}

1 个答案:

答案 0 :(得分:8)

如果不依赖于抽象来代替与SLogger的紧密耦合,那么就无法独立地测试foo()

我建议你为SLogger定义一个接口来实现;最低限度,举个例子:

public interface ILogger
{
    void LogInformation();
}

我进一步建议您在班级中提供ILogger的实例&#39;构造函数,作为dependency injection的一种形式,让您的类调用注入依赖项的方法:

public class Bar
{
    private readonly ILogger _logger;

    public Bar(ILogger logger)
    {
        _logger = logger;
    }

    public void Foo()
    {
        _logger.LogInformation();
    }
}

从您的调用代码中,您现在可以提供ILogger的实际实现,无论是SLogger的单例实例,还是单元测试的模拟实现:

//Real call
var myBar = new Bar(SLogger.Instance);

//From a test
var testBar = new Bar(new Mock<ILogger>().Object);

Stack Overflow和Web上有大量资源可以了解依赖注入和控制模式的反转,但Mark Seemann's blog是一个很好的起点。