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

Sta*_*ful 3 .net c# singleton unit-testing 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
     }
}
Run Code Online (Sandbox Code Playgroud)

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

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

还有其他办法吗?

void foo()
{
   // Business logic

   SLogger.Instance.LogInformation();

   // Business logic
}
Run Code Online (Sandbox Code Playgroud)

Pre*_*lot 8

没有抽象依赖而不是紧密耦合SLogger,就没有办法foo()独立测试.

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

public interface ILogger
{
    void LogInformation();
}
Run Code Online (Sandbox Code Playgroud)

我还建议您ILogger在类的构造函数中提供一个实例,作为依赖注入的一种形式,并让您的类调用注入依赖项的方法:

public class Bar
{
    private readonly ILogger _logger;

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

    public void Foo()
    {
        _logger.LogInformation();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

//From a test
var testBar = new Bar(new Mock<ILogger>().Object);
Run Code Online (Sandbox Code Playgroud)

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