我有以下课程:
public class UkFileHandler: FileHandler<UkFileHandler.FileMapper>
{
public class FileMapper : LookUpFieldDefinition
{
public int Name => 1;
public int Address1 => 4;
public int Address2 => 5;
}
public UkFileHandler(ILoggerFactory loggerFactory, IRecordParser recordParser,
IUnzipper unzipper, IFileStore fileStore, IRecordWriter writer)
: base(recordParser, unzipper, fileStore, writer)
{
Logger = loggerFactory.Create<UkFileHandler>();
}
protected override ILogger Logger { get; }
我正在尝试在单元测试中对此进行模拟,尝试如下:
[Test]
public void Test()
{
var mockLoggerFactory = new Mock<ILoggerFactory>();
var mockedILogger = new Mock<ILogger>();
mockLoggerFactory.Setup(lf=> lf.Create<UkFileHandler>()).Returns(mockedILogger.Object);
var mockUnzipper = new Mock<IUnzipper>();
var mockFileStore = new Mock<IFileStore>();
var mockFileWriter = new Mock<IRecordWriter>();
var mockFileHandler = new Mock<UkFileHandler>
(mockLoggerFactory.Object, new RecordParser(mockLoggerFactory.Object),
mockUnzipper.Object, mockFileStore.Object, mockFileWriter.Object);
// commented out code which calls method
Assert.IsNotNull(result);
}
我正在使用如下所示的自定义ILoggerFactory
:
public interface ILoggerFactory
{
ILogger Create<T>();
}
}
我的问题是,在运行测试时,Logger
实例为Null。我无法在这里错过任何东西的地方-有人可以帮忙吗?
答案 0 :(得分:0)
问题是:
protected override ILogger Logger { get; }
在您的层次结构中,Logger属性是虚拟的或抽象的。但是有一个简单的解决方法。
只需将此吸气剂转换为UkFileHandler
中的完整属性即可。像这样:
public class UkFileHandler: FileHandler<UkFileHandler.FileMapper>
{
private readonly ILogger logger;
public class FileMapper : LookUpFieldDefinition
{
public int Name => 1;
public int Address1 => 4;
public int Address2 => 5;
}
public UkFileHandler(ILoggerFactory loggerFactory, IRecordParser recordParser,
IUnzipper unzipper, IFileStore fileStore, IRecordWriter writer)
: base(recordParser, unzipper, fileStore, writer)
{
logger = loggerFactory.Create<UkFileHandler>();
}
protected override ILogger Logger => logger;
}
答案 1 :(得分:0)
第一个问题是,UkFileHandler是SUT吗?如果是这样,您通常不会嘲笑它。
它为空的原因是Logger属性是虚拟的或抽象的。您将在UkFileHandler中覆盖它,因此在继承层次结构中的某个位置将其标记为虚拟或抽象。完成后,即使您在构造函数中进行设置,Moq仍可以代理它并将其初始化为默认值(空)。
几种解决方法。
鉴于您在嘲笑一个实现,mockFileHandler.CallBase = true;
将允许未明确设置的任何内容按照该实现工作。
另一种方法是设置Logger属性。由于受到保护,因此您必须执行以下操作:
mockFileHandler.Protected().Setup<ILogger>("Logger").Returns(mockedILogger.Object);