Battle of the framework: Testing a Webpart

Time to see the difference between Moles and Isolator code. Let’s start with the code under test (a webpart):

public class NewMessagesCountWebPart : WebPart
{
    private Label lblNewMessages;

    protected void CreateChildControls(int i)
    {
        CreateChildControls();
    }  
    protected override void CreateChildControls()
    {
        lblNewMessages = new Label();
        lblNewMessages.Text = GetMessageNumberText();

        this.Controls.Add(lblNewMessages);
        base.CreateChildControls();
    }

    private string GetMessageNumberText()
    {
        using (SPSite site = new SPSite("http://sharepoint.typemock.com"))
        {
            using (SPWeb web = site.OpenWeb())
            {
                SPList messages = web.Lists["Messages"];
                int numberOfItems = messages.ItemCount;
                if (numberOfItems == 0)
                {
                    return "No new messages.";  
                }
                else
                {
                    return "New messages: " + numberOfItems;
                }
            }
        }
    }
}

Obviously, the problem is the private GetMessageNumberText method. Let’s see how Moles handles the faking. Take a deep breath:

[HostType("moles")]
[TestMethod]
public void GetMessageNumberText_ZeroMessages_NoNewMessagesText()
{
    // Arrange
    MSPSite.ConstructorString = (site, url) =>
    {
        new MSPSite(site)
        {
            OpenWeb = () => new MSPWeb()
            {
                ListsGet = () => new MSPListCollection()
                {
                    ItemGetString = (nameList) =>
                        new MSPList()
                    {
                        ItemCountGet = () => { return 0; }
                    }
                },
                Dispose = () => { }
            },
            Dispose = () => { }
        };
    };

    // Act
    NewMessagesCountWebPart webPart = new NewMessagesCountWebPart();
    string result = (string)
        typeof(NewMessagesCountWebPart)
        .GetMethod("GetMessageNumberText",
            BindingFlags.Instance | BindingFlags.NonPublic)
        .Invoke(webPart, null);

    // Assert
    Assert.AreEqual("No new messages.", result);
}

Notice the Lambda manipulation, and man, if you get it wrong, you need to dig deep. Another thing to note is the need to specify the empty implementation for the Dispose methods. The implementation is to throw if not specified. Finally, there’s the reflection use for invoking the method under test, not so big deal, but something you need to understand as well.

Behold the Isolator test:

[TestMethod]
public void GetMessageNumberText_ZeroMessages_NoNewMessagesText()
{
    // Arrange
    var fakeSite = Isolate.Fake.Instance<SPSite>();
    Isolate.Swap.NextInstance<SPSite>().With(fakeSite);
    Isolate.WhenCalled(() =>
        fakeSite.OpenWeb().Lists["Messages"].ItemCount)
        .WillReturn(0);

    // Act
    NewMessagesCountWebPart webPart = new NewMessagesCountWebPart();
    string result = (string) Isolate.Invoke.Method(webPart, "GetMessageNumberText");
    // Assert
    Assert.AreEqual("No new messages.", result);
   
}

I like this better.

Share Button

Leave a Reply

%d bloggers like this: