2016-08-25 11 views
1

Хорошо, воспроизводить, вот то, что вам нужноперечислив Передразнивало Индексатор Свойство Заставляет Коллекция пустеть

public interface IWorkbookSet 
{ 
    IWorkbooks Workbooks { get; } 
} 

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

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

Настройка тест Microsoft блока, используя следующий код

[TestInitialize] 
public void Initialize() 
{ 
    List<string> 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 = 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); 

     fakeWorksheetsList.Add(tmpMock.Object); 
    } 

    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()); 
    mockWorksheets.SetupGet(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.SetupGet(m => m.Count).Returns(fakeWorkbooksList.Count); 

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

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

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

    Assert.AreEqual(expected, actual); 
    Assert.AreEqual(12, workbookSet.Workbooks[0].Worksheets.Count); 
} 

В настоящее время в метод испытания, сделать это

[TestMethod] 
public async Task StrucutreGenerationAsyncTest() 
{ 
    foreach (IWorksheet ws in mockWorkbookSet.Object.Workbooks[0].Worksheets) 
     Trace.WriteLine("1111 ws = " + ws.Name); 

    foreach (IWorksheet ws in mockWorkbookSet.Object.Workbooks[0].Worksheets) 
     Trace.WriteLine("2222 ws = " + ws.Name); 
} 

Выход:

Test Name: StrucutreGenerationAsyncTest 
Test Outcome: Passed 
Result StandardOutput: 
Debug Trace: 
1111 ws = Master 
1111 ws = A 
1111 ws = B 
1111 ws = C 
1111 ws = __ParentA 
1111 ws = D 
1111 ws = wsgParentB 
1111 ws = E 
1111 ws = F 
1111 ws = __ParentC 
1111 ws = __ParentD 
1111 ws = G 

Первый foreach Перечислим IWorksheets, второй не (?), Как mockWorkbookSet.Object.Workbooks[0].Worksheets теперь пуст.

Еще более странным это

[TestMethod] 
public async Task StrucutreGenerationAsyncTest() 
{ 
    if (mockWorkbookSet.Object.Workbooks[0].Worksheets 
      .Cast<IWorksheet>().Any(ws => ws.Name.Compare("Master"))) 
     Trace.WriteLine("Match!"); 

    foreach (IWorksheet ws in mockWorkbookSet.Object.Workbooks[0].Worksheets) 
     Trace.WriteLine("1111 ws = " + ws.Name); 

    foreach (IWorksheet ws in mockWorkbookSet.Object.Workbooks[0].Worksheets) 
     Trace.WriteLine("2222 ws = " + ws.Name); 
} 

Выход:

Test Name: StrucutreGenerationAsyncTest 
Test Outcome: Passed 
Result StandardOutput: 
Debug Trace: 
Match! 
1111 ws = A 
1111 ws = B 
1111 ws = C 
1111 ws = __ParentA 
1111 ws = D 
1111 ws = wsgParentB 
1111 ws = E 
1111 ws = F 
1111 ws = __ParentC 
1111 ws = __ParentD 
1111 ws = G 

Куда "Мастер" ушел? Это похоже на акт перечисления, который удаляет элементы из коллекции. Почему это происходит и как я могу это исправить?


Изменить # 1: Я попытался насмешливый нумератор, используя метод, как следует

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()); 
mockWorksheets.SetupGet(m => m.Count).Returns(fakeWorksheetsList.Count); 

С

private IEnumerator<IWorksheet> WorksheetList() 
{ 
    foreach (string name in fakeSheetNames) 
    { 
     var mock = new Mock<IWorksheet>(); 
     mock.Setup(p => p.Name).Returns(name); 
     mock.Setup(p => p.Visible) 
      .Returns(parentPrefixes.Any(p => name.StartsWith(p)) ? 
        SheetVisibility.Hidden : 
        SheetVisibility.Visible); 
     yield return mock.Object; 
    } 
} 

Это не поможет.

+0

И, наконец, проблема. Элементы не удаляются. Итератор не сбрасывается, поскольку один и тот же экземпляр используется для всех вызовов из-за установки moq. – Nkosi

ответ

1
mockWorksheets.Setup(m => m.GetEnumerator()).Returns(fakeWorksheetsList.GetEnumerator()); 

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

Если вы хотите новый нумератор при каждом вызове, то вам необходимо пройти Returns лямбда-выражение:

mockWorkSheets.Setup(m => m.GetEnumerator()).Returns(() => fakeWorksheetsList.GetEnumerator()); 

Лямбда будет вызываться каждый раз, когда GetEnumerator() называется. Так что теперь перечисление макета несколько раз должно работать так, как ожидалось.

Ссылка Moq First() Last() and GetEnumerator() wierdness

+0

Приятный помощник, хорошо открытый! Благодарю. – MoonKnight

Смежные вопросы