2016-08-24 2 views
3

Я хочу знать, как я могу издеваться индексированное свойство и есть много вопросов, на этом:Mock только для чтения Индексатор недвижимости

  1. Moq an indexed property and use the index value in the return/callback
  2. How to MOQ an Indexed property
  3. How to Moq Setting an Indexed property

и др , Но в моем случае есть дополнительная сложность. Индексированное свойство только для чтения. Таким образом, мне нужно, чтобы быть в состоянии проверить кусок кода, который делает следующее

if (workbook.Worksheets.Cast<IWorksheet>().Any(
     ws => ws.Name.CompareNoCase(Keywords.Master))) 
{ 
    ... 
} 

где мы имеем следующую структуру класса

public interface IWorkbook 
{ 
    IWorksheets Worksheets { get; } 
} 

public interface IWorksheets : IEnumerable 
{ 
    IWorksheet this[int index] { get; } 
    IWorksheet this[string name] { get; } 
    int Count { get; } 
    IWorksheet Add(); 
    IWorksheet AddAfter(IWorksheet sheet); 
    IWorksheet AddBefore(IWorksheet sheet); 
    bool Contains(IWorksheet worksheet); 
} 

public interface IWorksheet 
{ 
    string Name { get; set; } 
} 

Так что в моем методе испытаний, я пытался (и не) для этого, переопределяя метод GetEnumerator(), поскольку это именно то, что вызывает Cast(); Я делаю это следующим образом:

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); 
} 

Mock<IWorkbook> mockWorkbook = new Mock<IWorkbook>(); 
mockWorkbook 
    .Setup(p => p.Worksheets.GetEnumerator()) 
    .Returns(worksheetMockList.GetEnumerator()); 

// I can't do this as per the threads referenced above, as the property is read only. 
//for (int i = 0; i < worksheetMockList.Count; ++i) 
    //mockWorkbook.SetupGet(p => p.Worksheets[i] = worksheetMockList[i])... 

Как я могу дразнить мой workbook.Worksheets читать только итератора недвижимость?


У меня есть еще один уровень абстракции. Мне нужно добавить IWorkbook в коллекцию IWorkbooks (как мы это делали для IWorksheets). Я не ставил это в исходный вопрос, поскольку он просто делает то же самое, что и мы, для IWorksheets, как бы он ни работал. Интерфейсы

public interface IWorkbookSet 
{ 
    ... 
    IWorkbooks Workbooks { get; } 
} 

и

public interface IWorkbooks : IEnumerable 
{ 
    IWorkbook this[int index] { get; } 
    IWorkbook this[string name] { get; } 
    int Count { get; } 
    ... 
} 

Так, чтобы попытаться справиться с этим я насмешливым следующим образом после большого ответа ниже. Однако нижние петли не работают должным образом.

List<string> fakeSheetNames = new List<string>() 
{ 
    "Master", 
    "A", 
    "B", 
    "C", 
    "__ParentA", 
    "D", 
    "wsgParentB", 
    "E", 
    "F", 
    "__ParentC", 
    "__ParentD", 
    "G" 
}; 


Mock<IWorkbook> mockWorkbook = new Mock<IWorkbook>(); 
List<IWorksheet> worksheetMockList = new List<IWorksheet>(); 
foreach (string name in fakeSheetNames) 
{ 
    Mock<IWorksheet> tmpWorksheetMock = new Mock<IWorksheet>(); 
    tmpWorksheetMock.Setup(p => p.Name).Returns(name); 
    tmpWorksheetMock.Setup(p => p.Visible) 
     .Returns(parentPrefixes.Any(p => name.StartsWith(p)) ? 
      SheetVisibility.Hidden : 
      SheetVisibility.Visible); 

    worksheetMockList.Add(tmpWorksheetMock.Object); 
} 
var mockWorksheets = new Mock<IWorksheets>(); 
mockWorksheets.Setup(m => m[It.IsAny<int>()]).Returns<int>(index => worksheetMockList[index]); 
mockWorksheets.Setup(m => m.GetEnumerator()).Returns(worksheetMockList.GetEnumerator()); 

mockWorkbook 
    .Setup(p => p.Worksheets) 
    .Returns(mockWorksheets.Object); 
mockWorkbook.Setup(p => p.Name).Returns("Name"); 
mockWorkbook.Setup(p => p.FullName).Returns("FullName"); 

// This works. 
foreach (IWorksheet ws in mockWorkbook.Object.Worksheets) 
    Trace.WriteLine(ws.Name); 

mockWorkbookSet = new Mock<IWorkbookSet>(); 
var mockWorkbooks = new Mock<IWorkbooks>(); 
List<IWorkbook> workbookMockList = new List<IWorkbook>() { mockWorkbook.Object }; 

mockWorkbooks.Setup(m => m[It.IsAny<int>()]).Returns<int>(index => workbookMockList[index]); 
mockWorkbooks.Setup(m => m.GetEnumerator()).Returns(workbookMockList.GetEnumerator()); 
mockWorkbookSet 
    .Setup(p => p.Workbooks) 
    .Returns(mockWorkbooks.Object); 

// Count is zero here?? 
foreach (IWorkbook wb in mockWorkbookSet.Object.Workbooks) 
    Trace.WriteLine(wb.Worksheets.Count); 

Большое спасибо.


Edit # 2: Использование кода У меня есть интересное поведение ...

// Setup test. 
var workbookSet = mockWorkbookSet.Object; 
var actual = workbookSet 
    .Workbooks[expectedWorkBooksIndex] 
    .Worksheets[expectedWorkSheetIndex]; 

// This prints "A" - GOOD! 
Trace.WriteLine("Actual " + actual.Name); 

// This passes. 
Assert.AreEqual(expected, actual); 

// This works. 
foreach (IWorksheet ws in mockWorkbook.Object.Worksheets) 
    Trace.WriteLine(ws.Name); 

// This works. 
Trace.WriteLine(mockWorkbookSet.Object.Workbooks[0].Name); 

// This does not write anything - WHY? 
foreach (IWorksheet ws in mockWorkbookSet.Object.Workbooks[0].Worksheets.Cast<IWorksheet>()) 
    Trace.WriteLine(ws.Name); 

// This fails. 
foreach (IWorkbook workbook in workbookSet.Workbooks.Cast<IWorkbook>()) 
    Assert.IsTrue(workbook.Worksheets.Count > 0); 

ответ

2

с помощью

mockWorkSheets 
    .Setup(m => m[It.IsAny<int>()]) 
    .Returns<int>(index => worksheetMockList[index]); 

где It.IsAny<int>() и .Returns<int>(index => ...) предоставляет доступ к значению, передаваемому в макете Вы можете получить доступ к индексу в методе .Returns.

В следующем примере показано, как настроить издевается

[TestMethod] 
public void Mock_Readonly_Indexer_Property() { 
    //Arrange 
    var parentPrefixes = new List<string>() { "__", "wsg" }; 
    var fakeSheetNames = new List<string>(){ 
     "Master", 
     "A", 
     "B", 
     "C", 
     "__ParentA", 
     "D", 
     "wsgParentB", 
     "E", 
     "F", 
     "__ParentC", 
     "__ParentD", 
     "G" 
    }; 

    //Worksheets 
    var fakeWorkSheetsList = new List<IWorksheet>(); 
    foreach (string name in fakeSheetNames) { 
     var tmpMock = Mock.Of<IWorksheet>(); 
     tmpMock.Name = name; 
     tmpMock.Visible = parentPrefixes.Any(p => name.StartsWith(p)) ? 
       SheetVisibility.Hidden : 
       SheetVisibility.Visible; 

     fakeWorkSheetsList.Add(tmpMock); 
    } 

    var mockWorkSheets = new Mock<IWorksheets>(); 
    mockWorkSheets.Setup(m => m[It.IsAny<int>()]) 
     .Returns<int>(index => fakeWorkSheetsList[index]); 
    mockWorkSheets.Setup(m => m.GetEnumerator()) 
     .Returns(() => fakeWorkSheetsList.GetEnumerator()); 
    //Assuming a Count property exists 
    mockWorkSheets.Setup(m => m.Count).Returns(fakeWorkSheetsList.Count); 

    //Workbook 
    var mockWorkbook = new Mock<IWorkbook>(); 
    mockWorkbook.Setup(p => p.Name).Returns("Name"); 
    mockWorkbook.Setup(p => p.FullName).Returns("FullName"); 
    mockWorkbook.Setup(p => p.Worksheets).Returns(mockWorkSheets.Object); 

    //Workbooks 
    var fakeWorkbooksList = new List<IWorkbook>() { mockWorkbook.Object }; 

    var mockWorkbooks = new Mock<IWorkbooks>(); 
    mockWorkbooks.Setup(m => m[It.IsAny<int>()]) 
     .Returns<int>(index => fakeWorkbooksList[index]); 
    mockWorkbooks.Setup(m => m.GetEnumerator()) 
     .Returns(() => fakeWorkbooksList.GetEnumerator()); 
    mockWorkbooks.Setup(m => m.Count).Returns(fakeWorkbooksList.Count); 

    //WorkbookSet 
    var mockWorkbookSet = new Mock<IWorkbookSet>(); 
    mockWorkbookSet.Setup(m => m.Workbooks).Returns(mockWorkbooks.Object); 

    var workbookSet = mockWorkbookSet.Object; 

    var expectedWorkBooksIndex = 0; 
    var expectedWorkSheetIndex = 1; 
    var expected = fakeWorkSheetsList[expectedWorkSheetIndex]; 

    //Act 
    var actual = workbookSet 
     .Workbooks[expectedWorkBooksIndex] 
     .Worksheets[expectedWorkSheetIndex]; 

    //Assert 
    Assert.AreEqual(expected, actual); 

    foreach (IWorkbook workbook in workbookSet.Workbooks) { 
     Assert.IsTrue(workbook.Worksheets.Count > 0); 
    } 

} 
+0

Большое спасибо за вашу помощь здесь, но я все еще возникают проблемы с этим. Вы можете проверить редактирование?Я награду за вашу помощь в свое время ... – MoonKnight

+0

@ Killercam. У вас есть кусочки одной и той же общей проблемы, возникающей среди разных вопросов. Я попросил некоторую информацию по одному из других вопросов, чтобы помочь прояснить проблему, чтобы я мог воспроизвести вашу проблему и предоставить полное решение, но запретил, что я только что показал примеры того, как исправить конкретные проблемы, о которых вы просили. Затем вы могли бы объединить ответы, чтобы решить общую проблему. – Nkosi

+0

Да, извините. Я понял половину пути в другом потоке, который я задал о проблеме так, чтобы это было недостаточно кратким. Я действительно не понял проблему (только свойства индексатора только для чтения). Я не сделал этого по какой-либо другой причине, ясности. Во всяком случае, я опередил себя; редактирование недоступно. Еще раз спасибо за все ваше время, это очень ценится. – MoonKnight

2

Возможно, вы ищете это?

mockWorkbook.SetupGet(wb => wb.Worksheets[i]).Returns(() => worksheetMockList[i]);