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?
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With