我在项目中使用 Autofac 作为 DI 容器。现在我已经开始在其中使用 Moq 创建单元测试。由于业务类的代码已经编写好了,所以我想避免对业务类进行重大更改。我在模拟 System.IO.XXX 类(如 FileSystemWatcher、Directory、File、StreamReader 等)时遇到问题。主要是因为它们要么是静态类,要么没有任何接口。
// 这是我的商务舱之一的样子
internal class SpanFileReader : ISpanFileReader
{
// Some private variables
private string _filePath;
private readonly ISpanLogger _spanLogger;
#region Public Properties
// Prorperties....
#endregion
#region Constructor
public SpanFileReader(string filePath)
{
_filePath = filePath;
_spanLogger = IocContainer.Instance.Container.Resolve<ISpanLogger>();
}
#endregion
#region Public Methods
public bool ReadSpanRecords(CancellationToken ct)
{
try
{
if (!VerifySpanFile())
return false;
_spanFileLines = new List<string>();
using (var streamReader = new StreamReader(_filePath))
{
while (!streamReader.EndOfStream)
{
// some logic
}
return true;
}
}
catch (OperationCanceledException operationCanceledException)
{
_spanLogger.UpdateLog("some message");
throw;
}
catch (Exception ex)
{
_spanLogger.UpdateLog("some message);
throw;
}
}
public void MoveFileToErrorFolder(string spanFileName)
{
var spanFilePath = AppConfiguration.SpanFolderPath + spanFileName;
var errorFilePath = AppConfiguration.SpanErrorFolderPath + spanFileName;
try
{
if (File.Exists(spanFilePath))
{
if (!File.Exists(errorFilePath))
{
_spanLogger.UpdateLog("some message");
File.Move(spanFilePath, errorFilePath);
_spanLogger.UpdateLog("some message");
}
else
{
File.Delete(spanFilePath);
_spanLogger.UpdateLog("some message");
}
}
else
{
_spanLogger.UpdateLog("some message");
}
}
catch (Exception ex)
{
_spanLogger.UpdateLog("some message");
throw ex;
}
}
}
现在我想以这样的方式使用StreamReader() ,我可以使用Autofac通过某个接口(比如IStreamReader)解析它的实例。因此,在为SpanFileReader()编写单元测试时,我可以在容器中注册IStreamReader 的Moq 实例并使用它而不是实际实例。我也想对File()类做类似的事情,这样我就可以提供我自己的 moq 实现,在测试 SUT(SpanFileReader实例)时调用它。有人可以建议一个正确的方法来处理这些场景。