我需要模拟一个共享点文档库,返回 6 个文件的列表。这是我用来创建模拟系统的逻辑。
public class SharePointDocLibraryUtilsTestFactory
{
private Mock<IPnPCoreSDKClient> _mockPnPCoreSDKClient;
private Mock<IPnPContext> _mockPnpContext;
private ITestOutputHelper _output;
public SharePointDocLibraryUtilsTestFactory(ITestOutputHelper output)
{
_mockPnPCoreSDKClient = new Mock<IPnPCoreSDKClient>();
_mockPnpContext = new Mock<IPnPContext>();
_mockPnPCoreSDKClient.Setup(client => client.GetPnPContextAsync(It.IsAny<string>())).ReturnsAsync(_mockPnpContext.Object);
_output = output;
}
public IList SetupMockSharePointLibrary()
{
var mockList = new Mock<IList>();
var mockRootFolder = new Mock<IFolder>();
var mockWeb = new Mock<IWeb>();
var subfolders = new List<IFolder>();
for (int i = 0; i < 3; i++)
{
var mockFolder = new Mock<IFolder>();
var mockFileCollection = new Mock<IFileCollection>();
var mockFiles = new List<IFile>();
for (int j = 0; j < 2; j++)
{
var mockFile = new Mock<IFile>();
mockFile.Setup(f => f.Name).Returns($"File_{i}_{j}.txt");
mockFile.Setup(f => f.ServerRelativeUrl).Returns($"/sites/me/Documents/folder_{i}/File_{i}_{j}.txt");
mockFiles.Add(mockFile.Object);
}
mockFileCollection.Setup(m => m.GetEnumerator()).Returns(() => mockFiles.GetEnumerator());
mockFolder.Setup(f => f.Files).Returns(mockFileCollection.Object);
subfolders.Add(mockFolder.Object);
}
// Setup folder collection to return our mock folders
var mockFolderCollection = new Mock<IFolderCollection>();
mockFolderCollection.Setup(m => m.GetEnumerator()).Returns(() => subfolders.GetEnumerator());
mockRootFolder.Setup(f => f.Folders).Returns(mockFolderCollection.Object);
// Setup the mock list to return the root folder and the correct item count
mockList.Setup(l => l.RootFolder).Returns(mockRootFolder.Object);
// Setup the mock web to return the mock list
mockWeb.Setup(web => web.Lists.GetByTitleAsync(It.IsAny<string>(), It.IsAny<Expression<Func<IList, object>>>()))
.ReturnsAsync(mockList.Object);
//mockList.Setup(l => l.RootFolder).Returns(mockRootFolder.Object);
//mockWeb.Setup(web => web.Lists.GetByTitleAsync(It.IsAny<string>(), It.IsAny<Expression<Func<IList, object>>>()))
// .ReturnsAsync(mockList.Object);
_output.WriteLine($"Total file list count {mockList.Object.ItemCount}");
return mockList.Object;
}
}
当我调试这段代码时,我可以看到mockFolderCollection是空的。这是我的即时窗口的输出:
mockFolderCollection
{Mock<IFolderCollection:1>}
Behavior: Default
CallBase: false
DefaultValue: Empty
DefaultValueProvider: {Moq.EmptyDefaultValueProvider}
Invocations: {Moq.InvocationCollection}
Name: "Mock<IFolderCollection:1>"
Object (Moq.Mock): {Mock<IFolderCollection:1>.Object}
Object: {Mock<IFolderCollection:1>.Object}
Setups: {Moq.SetupCollection}
Switches: Default
因为这是空的,当它调用 SUT 时,当它遇到这个特定函数时,我会收到一个 null 错误:
private async Task ProcessFolderAsync(IFolder folder, SharePointDocLibraryInventory result, bool recursive, string checksumType)
{
// Process files in the current folder
foreach (var file in folder.Files)
{
string checksum = await GenerateChecksumAsync(file, checksumType);
result.Files.Add(new SynchronizedSharePointDocument
{
Name = file.Name,
FullPath = file.ServerRelativeUrl,
RelativePath = file.ServerRelativeUrl.Replace(folder.ServerRelativeUrl, "").TrimStart('/'),
Checksum = checksum
});
result.TotalFiles++;
}
// Optionally process subfolders recursively
if (recursive)
{
await folder.LoadAsync(f => f.Folders);
foreach (var subfolder in folder.Folders)
{
result.TotalSubdirectories++;
await ProcessFolderAsync(subfolder, result, recursive, checksumType);
}
}
}
文件夹参数为空。
集合不为空,这个通过的测试证明了这一点:
[Fact]
public void AttemptRepro()
{
var factory = new SharePointDocLibraryUtilsTestFactory(output);
var actual = factory.SetupMockSharePointLibrary();
Assert.Equal(3, actual.RootFolder.Folders.Count());
}
您在立即窗口中看到的
Empty
值只是默认起订量 DefaultValue
。这是一个enum
,Empty
的文档说:
默认行为,为值类型(即default(int))生成空值、空数组和可枚举,为所有其他引用类型生成空值。
总而言之,集合通常是确定性的,这意味着它们已经是可测试的。不要使用动态模拟创建Test Doubles,而是帮自己一个忙并使用真正的集合类。这会容易得多。