C# 模拟基类保护属性

C# 模拟基类保护属性,c#,mocking,nunit,moq,log4net,C#,Mocking,Nunit,Moq,Log4net,我目前正在创建一个Mock单元测试,用于测试LogManagerLogger.Error()类方法调用,如下所示 public class Test : BaseClass { public override void DoSomething(object value) { try { if (value == null) { throw new Exception(); }

我目前正在创建一个
Mock
单元测试,用于测试
LogManager
Logger.Error()
类方法调用,如下所示

public class Test : BaseClass
{
   public override void DoSomething(object value)
   {
      try
      { 
         if (value == null)
         {
             throw new Exception();
         }         
      }
      catch(exception ex)
      {
         Logger.Error("Exception raised!", ex);
      }
   }
}
我的类使用了一个抽象基类,该基类的
ILog

public abstract class BaseClass
{
   protected ILog Logger => LogManager.GetLogger(GetType());
}
问题是如何模拟这个基类属性
Logger
,以便测试是否引发了
Logger.Error()

这是我的单元测试

[Test]
public void PassingNullParamShouldRaiseError()
{
    // Arrange
    var mockLog = new Mock<ILog>();
    var sut = new Test();

    // Action
    sut.DoSomething(null);

    // Assert
    mockLog.Verify(x => x.Error("Exception raised!"), Times.Once());
}
[测试]
public void PassingNullParamShouldRaiseError()
{
//安排
var mockLog=new Mock();
var sut=新测试();
//行动
sut.DoSomething(空);
//断言
验证(x=>x.Error(“引发异常!”),Times.Once();
}

如果将基本属性设置为虚拟

现在,您可以在测试时使用模拟来覆盖该属性

[Test]
public void PassingNullParamShouldRaiseError() {
    // Arrange
    var mockLog = new Mock<ILog>();

    var sut = new Mock<Test>() {
        CallBase = true //Important to be able to call base member
    };

    //override default behavior of protected logger
    sut.Protected()
        .Setup<ILog>("Logger")
        .Returns(mockLog.Object);

    // Act
    sut.Object.DoSomething(null);

    // Assert
    mockLog.Verify(x => x.Error("Exception raised!", It.IsAny<Exception>()), Times.Once());
}
谁的实现可以包装这种代码味道

public class DefaultLoggerFactory : ILoggerFactory {
    public ILog GetLogger(Type type) => LogManager.GetLogger(type);
}
可用于获取所需日志的

public class Test  {
    private readonly ILog logger;

    public Test(ILoggerFactory logs)  {
        logger = logs.GetLogger(GetType());
    }

    public void DoSomething(object value) {
        try {
            if (value == null) {
                throw new Exception();
            }
        } catch (Exception ex) {
            logger.Error("Exception raised!", ex);
        }
    }
}

谢谢你的回答。解释得很好,提示不要紧密耦合基类。
public class DefaultLoggerFactory : ILoggerFactory {
    public ILog GetLogger(Type type) => LogManager.GetLogger(type);
}
public class Test  {
    private readonly ILog logger;

    public Test(ILoggerFactory logs)  {
        logger = logs.GetLogger(GetType());
    }

    public void DoSomething(object value) {
        try {
            if (value == null) {
                throw new Exception();
            }
        } catch (Exception ex) {
            logger.Error("Exception raised!", ex);
        }
    }
}