我正在尝试弄清楚如何或是否可以使用 Moq 执行以下操作
public class Download
{
private IFoo ifoo;
public Download(IFoo ifoo)
{
this.ifoo = ifoo;
}
public void Download()
{
var files = Directory.GetFiles("filepath"); //<<<===
foreach (var item in files)
{
// do something
}
}
}
在单元测试中。
// Arrange
var mockFoo = new Mock<IFoo>();
mockFoo.setup( s => s.Bar()).returns(true);
var foo = new Foo(mockFoo.Object);
// Act
foo.Download()
如何模拟 files
变量,因此该方法使用模拟版本。这甚至是正确的方法吗?因为我不是在模拟类,而是在模拟依赖项,所以我该如何设置文件变量,以便它查看模拟文件字符串 []。
最佳答案
您需要依赖抽象来获取文件,而不是硬依赖 System.IO.Directory
:
public interface IFileProvider
{
string[] GetFiles(string path);
}
public class PhysicalFileProvider : IFileProvider
{
public string[] GetFiles(string path)
{
return Directory.GetFiles(path);
}
}
您将以与注入(inject) IFoo
完全相同的方式注入(inject)抽象。
现在您可以使用 Moq 模拟 IFileProvider
,创建一个模拟来准确返回您希望它返回的字符串。
var fileProvider = new Mock<IFileProvider>();
fileProvider.Setup(x => x.GetFiles(It.IsAny<string>()))
.Returns(new[] {"file1.txt", "file2.txt"});
您还可以使用 Microsoft.Extensions.FileProviders.Physical它提供文件系统访问和抽象。
public class Download
{
private readonly IFoo _foo;
private readonly Microsoft.Extensions.FileProviders.IFileProvider _fileProvider;
public Download(IFoo foo, IFileProvider fileProvider)
{
_foo = foo;
_fileProvider = fileProvider;
}
public void SomethingWithFiles()
{
var files = _fileProvider.GetDirectoryContents("filepath")
.Where(item => !item.IsDirectory);
foreach (var item in files)
{
// something
}
}
}
具体实现是PhysicalFileProvider
。
还有一个变化。不是注入(inject)接口(interface),而是注入(inject)委托(delegate):
public delegate string[] GetFilesFunction(string path);
public class Download
{
private readonly IFoo _foo;
private readonly GetFilesFunction _getFiles;
public Download(IFoo foo, GetFilesFunction getFiles)
{
_foo = foo;
_getFiles = getFiles;
}
...
这更容易模拟。您甚至不需要最小起订量。
var subject = new Download(mockedFoo, path => new []{"file1.txt","file2.txt"} );
关于c# - 我如何模拟 Directory.GetFiles?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53620516/