title: Mock a Custom Collection using Moq
body: <p>I have the following types in a 3rd party library</p>
  
  <pre><code>public interface IWorkbook : IPrintable
  {
      ...
      IWorksheets Worksheets { get; }
  }
  </code></pre>
  
  <p>The worksheets interface is </p>
  
  <pre><code>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);
  }
  </code></pre>
  
  <p>I have a method that I want to unit test that takes an <code>IWorkbook</code> and iterates through the contained worksheets. My problem is how I can use Moq to create a mock collection for <code>IWorksheets</code>. The <code>IWorksheet</code> interface is</p>
  
  <pre><code>public IWorksheet
  {
      ...
      public Name { get; set; } // This is the only property I am interested in.
  }
  </code></pre>
  
  <p>So how can I generate a fake <code>IWorkbook</code> which has a fake collection (<code>IWorksheets</code>) of <code>IWorksheet</code>s?</p>
  
  <p>I have started out with </p>
  
  <pre><code>[TestInitialize]
  public void Initialize()
  {
      List&lt;string&gt; fakeSheetNames = new List&lt;string&gt;()
      {
          "Master",
          "A",
          "B",
          "C",
          "__ParentA", 
          "D",
          "wsgParentB", 
          "E",
          "F",
          "__ParentC",
          "__ParentD",
          "G"
      };
  
      List&lt;IMock&lt;IWorksheet&gt;&gt; sheetMockList = new List&lt;IMock&lt;IWorksheet&gt;&gt;();
      foreach (string name in fakeSheetNames)
      {
          Mock&lt;IWorksheet&gt; tmpMock = new Mock&lt;IWorksheet&gt;();
          tmpMock.Setup(p =&gt; p.Name).Returns(name);
          sheetMockList.Add(tmpMock);
      }
  
      var mockWorksheets = new Mock&lt;IWorksheets&gt;();
      mockWorksheets.Setup(p =&gt; p).Returns(sheetMockList);
      ...
  }
  </code></pre>
  
  <p>But I cannot do this as (obviously)</p>
  
  <blockquote>
    <p>cannot convert from 'System.Collections.Generic.List>' to 'SpreadsheetGear.IWorksheets'  </p>
  </blockquote>
  
  <p>How can I mock the <code>IWorksheets</code> collection? </p>
  
  <hr>
  
  <p>So I now have the following code to create my mocks as per the answer below</p>
  
  <pre><code>    [TestClass]
  public class WorkbookStrucutreProviderTests
  {
      private Mock&lt;IWorkbookSet&gt; mockWorkbookSet;
      private readonly List&lt;string&gt; parentPrefixes = new List&lt;string&gt;() { "__", "wsg" };
  
      [TestInitialize]
      public void Initialize()
      {
          List&lt;string&gt; fakeSheetNames = new List&lt;string&gt;()
          {
              "Master",
              "A",
              "B",
              "C",
              "__ParentA", 
              "D",
              "wsgParentB", 
              "E",
              "F",
              "__ParentC",
              "__ParentD",
              "G"
          };
  
          List&lt;IWorksheet&gt; worksheetMockList = new List&lt;IWorksheet&gt;();
          foreach (string name in fakeSheetNames)
          {
              Mock&lt;IWorksheet&gt; tmpMock = new Mock&lt;IWorksheet&gt;();
              tmpMock.Setup(p =&gt; p.Name).Returns(name);
              tmpMock.Setup(p =&gt; p.Visible)
                  .Returns(parentPrefixes.Any(p =&gt; name.StartsWith(p)) ? 
                      SheetVisibility.Hidden : 
                      SheetVisibility.Visible);
  
              worksheetMockList.Add(tmpMock.Object);
          }
  
          List&lt;IWorkbook&gt; workbookMockList = new List&lt;IWorkbook&gt;();
          Mock&lt;IWorkbook&gt; mockWorkbook = new Mock&lt;IWorkbook&gt;();
          mockWorkbook
              .Setup(p =&gt; p.Worksheets.GetEnumerator())
              .Returns(worksheetMockList.GetEnumerator());
          workbookMockList.Add(mockWorkbook.Object);
  
          mockWorkbookSet = new Mock&lt;IWorkbookSet&gt;();
          mockWorkbookSet
              .Setup(p =&gt; 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);
                  }
              }
          }
      }
  </code></pre>
  
  <p>But in the <code>GenerateWorkbookStructureAsync()</code> method I have this bit of code</p>
  
  <pre><code>bool IsUserCostWorkbook = false;
  if (workbook.Worksheets.Cast&lt;IWorksheet&gt;().Any(
      ws =&gt; ws.Name.CompareNoCase(Keywords.Master)))
  {
      // TODO Extra check for UserCost template.
      IsUserCostWorkbook = true;          
  }
  </code></pre>
  
  <p>and here the <code>workbook.Worksheets</code> collection is empty. I thought my mock <code>GetEnumerator</code> would handle this; it doesn't. </p>
  
  <p>So how can I mock the <code>IWorksheets</code> so that I can do the following?</p>
  
  <pre><code>foreach (var ws in workbook.Worksheets.Cast&lt;IWorksheet&gt;())
  {
      ...
  }
  </code></pre>