2016-08-24 3 views
2

я следующие типы в 3-сторонней библиотекиMock пользовательской коллекции с помощью Moq

public interface IWorkbook : IPrintable 
{ 
    ... 
    IWorksheets Worksheets { get; } 
} 

Интерфейс рабочих листов является

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

У меня есть метод, который я хочу модульного тестирования, который принимает IWorkbook и выполняет итерацию через содержащиеся листы. Моя проблема в том, как я могу использовать Moq для создания коллекции для IWorksheets. Интерфейс IWorksheet является

public IWorksheet 
{ 
    ... 
    public Name { get; set; } // This is the only property I am interested in. 
} 

Так как я могу генерировать поддельные IWorkbook который имеет поддельную коллекцию (IWorksheets) в IWorksheet с?

Я начал с

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

Но я не могу сделать это как (очевидно)

не может конвертировать из 'System.Collections.Generic.List>' до 'SpreadsheetGear.IWorksheets'

Как я могу издеваться над коллекцией IWorksheets?


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

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

Но в методе GenerateWorkbookStructureAsync() у меня есть этот кусок кода

bool IsUserCostWorkbook = false; 
if (workbook.Worksheets.Cast<IWorksheet>().Any(
    ws => ws.Name.CompareNoCase(Keywords.Master))) 
{ 
    // TODO Extra check for UserCost template. 
    IsUserCostWorkbook = true;   
} 

и здесь коллекция workbook.Worksheets пуста. Я думал, что мой макет GetEnumerator справится с этим; это не так.

Так как я могу высмеять IWorksheets, чтобы я мог сделать следующее?

foreach (var ws in workbook.Worksheets.Cast<IWorksheet>()) 
{ 
    ... 
} 
+0

не должны IWorksheets реализовать IEnumerable ? Если нет, ваш sheetMockList должен быть нетипизированным списком – McNultyyy

+0

Это не мой код. Это сторонняя библиотека. 'IWorksheets' - это коллекция, в которой используется индекс. Мы можем применить это к 'IEnumerable ', используя Linq и' Cas () '. Но нет, он не реализует 'IEnumerable ' непосредственно. – MoonKnight

+0

Приведите пример того, что вы хотите проверить. Недостаточно информации в вашем примере – Nkosi

ответ

1

Следующий пример проходит при испытании

[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); 
} 
+0

К сожалению, это не работает. Я отредактирую сообщение ... – MoonKnight

+0

Хорошо пересматривая его сейчас – Nkosi

+0

Подождите. Я буду исследовать себя и вернуться к вам. Большое спасибо за ваше время и помощь, это очень ценится. – MoonKnight

1

Извините за псевдокода:

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); 
+0

Если вам нужно итерации, вы можете mock 'GetEnumerator()' – Serg046

+0

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

+0

Если это так, вы можете создать фальшивый итератор, который возвращает все ваши объекты, указанные выше, а затем издевается над 'GetEnumerator()' из 'worksheetsMock', чтобы вернуть этот фальшивый итератор. Я могу попытаться реализовать этот образец позже, если понадобится еще – Serg046

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