[英]Mock a Custom Collection using Moq
I have the following types in a 3rd party library 我在第3方库中有以下类型
public interface IWorkbook : IPrintable
{
...
IWorksheets Worksheets { get; }
}
The worksheets interface is 工作表界面是
public interface IWorksheets : IEnumerable
{
IWorksheet this[int index] { get; }
IWorksheet this[string name] { get; }
IWorkbookSet WorkbookSet { get; }
IWorksheet Add();
IWorksheet AddAfter(ISheet sheet);
IWorksheet AddBefore(ISheet sheet);
bool Contains(IWorksheet worksheet);
}
I have a method that I want to unit test that takes an IWorkbook
and iterates through the contained worksheets. 我有一个要进行单元测试的方法,该方法采用
IWorkbook
并遍历包含的工作表。 My problem is how I can use Moq to create a mock collection for IWorksheets
. 我的问题是如何使用Moq为
IWorksheets
创建模拟集合。 The IWorksheet
interface is IWorksheet
界面是
public IWorksheet
{
...
public Name { get; set; } // This is the only property I am interested in.
}
So how can I generate a fake IWorkbook
which has a fake collection ( IWorksheets
) of IWorksheet
s? 所以,我怎么能生成一个假
IWorkbook
其中有一个假的集合( IWorksheets
的) IWorksheet
S'
I have started out with 我已经开始
[TestInitialize]
public void Initialize()
{
List<string> fakeSheetNames = new List<string>()
{
"Master",
"A",
"B",
"C",
"__ParentA",
"D",
"wsgParentB",
"E",
"F",
"__ParentC",
"__ParentD",
"G"
};
List<IMock<IWorksheet>> sheetMockList = new List<IMock<IWorksheet>>();
foreach (string name in fakeSheetNames)
{
Mock<IWorksheet> tmpMock = new Mock<IWorksheet>();
tmpMock.Setup(p => p.Name).Returns(name);
sheetMockList.Add(tmpMock);
}
var mockWorksheets = new Mock<IWorksheets>();
mockWorksheets.Setup(p => p).Returns(sheetMockList);
...
}
But I cannot do this as (obviously) 但是我不能这样做(显然)
cannot convert from 'System.Collections.Generic.List>' to 'SpreadsheetGear.IWorksheets'
无法从“ System.Collections.Generic.List>”转换为“ SpreadsheetGear.IWorksheets”
How can I mock the IWorksheets
collection? 如何模拟
IWorksheets
集合?
So I now have the following code to create my mocks as per the answer below 所以我现在有以下代码按照下面的答案创建我的模拟
[TestClass]
public class WorkbookStrucutreProviderTests
{
private Mock<IWorkbookSet> mockWorkbookSet;
private readonly List<string> parentPrefixes = new List<string>() { "__", "wsg" };
[TestInitialize]
public void Initialize()
{
List<string> fakeSheetNames = new List<string>()
{
"Master",
"A",
"B",
"C",
"__ParentA",
"D",
"wsgParentB",
"E",
"F",
"__ParentC",
"__ParentD",
"G"
};
List<IWorksheet> worksheetMockList = new List<IWorksheet>();
foreach (string name in fakeSheetNames)
{
Mock<IWorksheet> tmpMock = new Mock<IWorksheet>();
tmpMock.Setup(p => p.Name).Returns(name);
tmpMock.Setup(p => p.Visible)
.Returns(parentPrefixes.Any(p => name.StartsWith(p)) ?
SheetVisibility.Hidden :
SheetVisibility.Visible);
worksheetMockList.Add(tmpMock.Object);
}
List<IWorkbook> workbookMockList = new List<IWorkbook>();
Mock<IWorkbook> mockWorkbook = new Mock<IWorkbook>();
mockWorkbook
.Setup(p => p.Worksheets.GetEnumerator())
.Returns(worksheetMockList.GetEnumerator());
workbookMockList.Add(mockWorkbook.Object);
mockWorkbookSet = new Mock<IWorkbookSet>();
mockWorkbookSet
.Setup(p => p.Workbooks.GetEnumerator())
.Returns(workbookMockList.GetEnumerator());
}
[TestMethod]
public async Task StrucutreGenerationAsyncTest()
{
WorkbookStructureProvider provider = new WorkbookStructureProvider();
await provider.GenerateWorkbookStructureAsync(mockWorkbookSet.Object);
foreach (var item in provider.Structure)
{
Trace.WriteLine("--" + item.Name);
if (item.HasChildren)
{
foreach (var child in item.Children)
{
Trace.WriteLine("-- --" + child.Name);
}
}
}
}
But in the GenerateWorkbookStructureAsync()
method I have this bit of code 但是在
GenerateWorkbookStructureAsync()
方法中,我有这段代码
bool IsUserCostWorkbook = false;
if (workbook.Worksheets.Cast<IWorksheet>().Any(
ws => ws.Name.CompareNoCase(Keywords.Master)))
{
// TODO Extra check for UserCost template.
IsUserCostWorkbook = true;
}
and here the workbook.Worksheets
collection is empty. 这里的
workbook.Worksheets
集合为空。 I thought my mock GetEnumerator
would handle this; 我以为我的模拟
GetEnumerator
可以解决这个问题; it doesn't. 没有。
So how can I mock the IWorksheets
so that I can do the following? 那么,如何模拟
IWorksheets
以便可以执行以下操作?
foreach (var ws in workbook.Worksheets.Cast<IWorksheet>())
{
...
}
The following example passes when tested 以下示例在测试时通过
[TestMethod]
public void Mock_Custom_Collection_Using_Moq() {
//Arrange
var parentPrefixes = new List<string>() { "__", "wsg" };
var fakeSheetNames = new List<string>(){
"Master",
"A",
"B",
"C",
"__ParentA",
"D",
"wsgParentB",
"E",
"F",
"__ParentC",
"__ParentD",
"G"
};
var worksheetMockList = new List<IWorksheet>();
foreach (string name in fakeSheetNames) {
var worksheet = Mock.Of<IWorksheet>();
worksheet.Name = name;
worksheet.Visible = parentPrefixes.Any(p => name.StartsWith(p)) ?
SheetVisibility.Hidden :
SheetVisibility.Visible;
worksheetMockList.Add(worksheet);
}
var mockWorkbook = new Mock<IWorkbook>();
mockWorkbook
.Setup(p => p.Worksheets.GetEnumerator())
.Returns(() => worksheetMockList.GetEnumerator());
var workbook = mockWorkbook.Object;
//Act
bool IsUserCostWorkbook = false;
if (workbook.Worksheets.Cast<IWorksheet>()
.Any(ws => ws.Name.Equals("Master", StringComparison.InvariantCultureIgnoreCase))) {
IsUserCostWorkbook = true;
}
//Assert
Assert.IsTrue(IsUserCostWorkbook);
}
Sorry for pseudo code: 对不起,伪代码:
var fakeWorksheet = new Mock<IWorksheet>();
//You can use AutoFixture here to auto-populate properties or you can set only required props
fakeWorksheet.Setup(p => p.Name).Returns("TestName");
var worksheetsMock = new Mock<IWorksheets>()
//here mock some members that you need
worksheetsMock.Setup(w => w.Add()).Returns(fakeWorksheet.Object);
var workbookMock = new Mock<IWorkbook>();
workbookMock.Setup(w => w.Worksheets).Returns(worksheetsMock.Object);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.