Search code examples
c#unit-testingoutlooknsubstitute

How do I mock Outlook.MailItem with multiple Attachments using NSubstitute?


I'm trying to unit test a static function that accepts an Outlook.MailItem argument type:

public static bool GetMailAndDoSomething(Outlook.MailItem mailitem)

Here is what I have so far in my test function:

using Outlook = Microsoft.Office.Interop.Outlook;
...
public void TestGetMailAndDoSomething()
{
    Outlook.MailItem mailItem = Substitute.For<Outlook.MailItem>();

    Outlook.Attachments attachments = Substitute.For<Outlook.Attachments>();
    attachments.Add(Substitute.For<Outlook.Attachment>());
    attachments.Add(Substitute.For<Outlook.Attachment>());
    attachments.Add(Substitute.For<Outlook.Attachment>());
    attachments.Add(Substitute.For<Outlook.Attachment>());

    mailItem.Attachments.GetEnumerator().Returns(attachments.GetEnumerator());

    Assert.True(Misc.GetMailAndDoSomething(mailItem));
}

Inside the GetMailAndDoSomething function, there is a piece of code that I want to test

foreach (Outlook.Attachment attachment in mailItem.Attachments)
{
       //do someting
}

However, the test program never reaches //do something because mailItem.Attachments always seem empty. This is what I see when my IDE breaks at the foreach line.

enter image description here

What do I need to fix in the test function so that the test program will reach //do something in the targeted function?


Solution

  • You are trying to perform implementations on an interface.

    Attachments is derive from IEnumerable

    [System.Runtime.InteropServices.Guid("0006303C-0000-0000-C000-000000000046")]
    public interface Attachments : System.Collections.IEnumerable
    

    Consider using an actual list as a memory store and then setting up the mock to return that

    var list = new List<Outlook.Attachment>();
    list.Add(Substitute.For<Outlook.Attachment>());
    list.Add(Substitute.For<Outlook.Attachment>());
    list.Add(Substitute.For<Outlook.Attachment>());
    list.Add(Substitute.For<Outlook.Attachment>());
    
    Outlook.Attachments attachments = Substitute.For<Outlook.Attachments>();
    attachments.GetEnumerator().Returns(list.GetEnumerator());
    
    Outlook.MailItem mailItem = Substitute.For<Outlook.MailItem>();
    mailItem.Attachments.Returns(attachments);
    
    //...