Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing ASP.NET Page.Form for unit tests

Fo unit testing ASP.NET controls I need a stubbed Page.

I can create an ASP.NET Page object in my unit tests by subclassing System.Web.UI.Page. However, I cannot find a way to set Page.Form. Adding a form with attribute (runat,server) does not work. Overloading the form in my Subclass does not give the required functionality.

Context: I try to unit test some homemade ASP.NET controls. These control require Page and Page.Form not to be null.

Any suggestions?

like image 207
Hans Avatar asked Feb 22 '11 14:02

Hans


People also ask

How do you stub in unit testing?

To use stubs, you have to write your component so that it uses only interfaces, not classes, to refer to other parts of the application. This is a good design practice because it makes changes in one part less likely to require changes in another. For testing, it allows you to substitute a stub for a real component.

What is stub in unit testing C#?

Stub: Stub is an object that holds predefined data and uses it to answer calls during tests. Such as: an object that needs to grab some data from the database to respond to a method call. Mocks: Mocks are objects that register calls they receive.

How do you structure unit tests?

A typical unit test contains 3 phases: First, it initializes a small piece of an application it wants to test (also known as the system under test, or SUT), then it applies some stimulus to the system under test (usually by calling a method on it), and finally, it observes the resulting behavior.


1 Answers

Try defining an IPage and IForm interface that implement the needed methods and properties and create classes that implements those interfaces and wraps a Page or Form class. This way you can test the logic in those controls, without calling into the ASP.NET framework during unit testing.

UPDATE:

Overriding the page property will be brittle and is not advisable. Instead, you should try to minimize the amount of untestable code, by extracting logic in methods that don't depend on any ASP.NET specific (hard to test) parts. Take a look at the following example:

public class MyLabel : Label
{
    protected override override void RenderContents(HtmlTextWriter writer)
    {
        IPage page = new PageWrapper(this.Page);
        this.MethodToTest(page);

        base.RenderContents(writer);
    }

    internal void MethodToTest(IPage page)
    {
        // Work with IPage interface.
        if (page.IsPostBack)
        {
            this.Text = string.Empty;
        }
    }
}

By extracting the logic out of methods that are hard to test, you can call those extracted methods directly in your tests. For instance:

[TestMethod]
public void MethodToTest_ScenarioToTest_ExpectedBehavior()
{
    // Arrange
    var label = new MyLabel();

    var page = new TestPage()
    {
        IsPostBack = true
    };

    // Act
    label.MethodToTest(page);

    // Assert
    Assert.IsTrue(string.Empty, label.Text);
}

It would be even better if you would be able to extract the code under test to it's own class and call it from your WebControl. This is however, not always possible.

I hope this makes sense.

like image 63
Steven Avatar answered Sep 29 '22 21:09

Steven