Published: 29 Apr 2011
By: John Katsiotis
Download Sample Code

In this article we explore how unit tests are created in an ASP.NET WebForms Application. Although there are sections that are specific to the MVP pattern, there are also a few tips and guidelines about Unit Testing of a Web Application in general.

Contents [hide]

Introduction

ASP.NET MVC is the new kid in town and everyone wants to use it. What happens though, if you can't migrate your application to ASP.NET MVC (ex: maintenance of a legacy Web Application)?

The purpose of this article is to explain how to test an ASP.NET Webforms Applications. How the Model-View-Presenter pattern is helping us in that, how do we use mock-up libraries to simulate objects like HttpContext and how do we use Visual Studio 2010 Testing Environment.

Testing Web Applications

First of all, when we want to test a Web Application we are considering two types of tests. Acceptance Tests and Unit Tests.

Acceptance Tests

Acceptance Tests are tests from a user prospective and most of the times an automated-browser testing tool is used (like WatiN, Selenium etc.) So we are testing the user experience, if our app works in different browsers, if client-validation works as it should etc.

Unit Tests

Unit Tests are tests dedicated to test our code, our business logic and validation, our database interaction and everything that are not related to how data is displayed. Although many times Unit Tests and Acceptance Test may have overlapping areas (example, when testing if a page works simultaneously validation is also being tested) it's important to have both in a project.

For now, let's focus on Unit Tests.

Example

Let's consider the following real world but simple example:

Almost every website has a contact page. The user enters his details and sends them to the server. The server processes the data and informs the user about the result. How can we test a page like this?

Figure 1: Screenshot - Contact Page

Screenshot - Contact Page

Explaining the MVP Pattern

The MVP pattern stands for Model-View-Presenter and doesn't differ a lot from MVC (Model-View-Controller). When an application is developed using the MVP pattern it's more testable because layers are being separated from each other. So each layer's responsibility is clearer thus easier to define test cases to run against. An excellent open-source framework that helps us build a WebForms application using the MVP Pattern is WebFormsMVP. This framework is being used in this example.

An implementation of the page above using the MVP Pattern along with a brief explanation of the pattern its self would be the following.

Model

Model is the class that holds the data of our page. In this case it is a simple class with three properties that are represented by our text fields and one property that holds if the Model is persisted or not to our database.

Listing 1: ContactModel.cs

It's also included just for reference the enProcessState enum.

Listing 2: enProcessState.cs

View

View, in this case, is the user control that displays the form and defines events – if necessary – that correspond to user actions. Because a view can be implemented in various ways an interface is being defined and the user control is implementing that interface.

Listing 3: IContactView.cs

The implementation of the interface is our user control.

Listing 4: ContactControl.ascx

And our code-behind is the following.

Listing 5: ContactControl.ascx.cs

Presenter

The presenter is responsible for passing the model to the view and subscribing to events that the view defines in order to execute appropriate actions.

Listing 6: ContactPresenter.cs

Project Structure

In order for UI to be separated from the Logic of our Application we have two (2) projects in our solution. The first is a Class Library project that contains the interface of the View, the Presenter and the Model. The second is the ASP.NET Website that contains the implementation of the view and everything else relevant to that like the ASPX page that contains the UserControl etc.

Figure 2: Project Structure in Visual Studio

Project Structure in Visual Studio

Unit Testing

Now that our project is fully explained we need to add a Test Project to our solution. Also we need to add the following assembly references to our Test Project:

  • System.Web
  • System.Web.Abstractions
  • WebFormsMvp

We also need to add a reference to our Logic Project.

NOTE

Notice that we don't add a reference to our Web project because the MVP pattern keeps the nicely separated so that we don't have to!

Simulating HttpContext

The biggest problem when testing a website is that you have to simulate the request from the client and other things like if the user is authenticated, etc.

This is where a mock-up framework comes handy. A mock-up framework is helping us to create objects or interfaces with any kind of behavior. Let's see it in action.

We will use Rhino.Mocks and to do that we will install the corresponding package from NuGet.

Fire up the Package Manager Console, set as default project the Test project and type Install-Package RhinoMocks. This will add all the necessary references to our test project.

Now we are ready to mock our HttpContext.

Listing 7: Simulating the HttpContext along with options like if the user is authenticated etc.

This above code is a function that creates a mocked HttpContext, sets whether the user is authenticated and the username of the current user.

So our if we want to test code that checks if the user is authenticated although we don't have an actual request Context.User.Identity.IsAuthenticated will work as expected!

NOTE

Notice that we can use the Stub method of a mocked object to demand properties or methods of that object return explicit values.

When creating a unit test it's also best to follow the AAA pattern. AAA stands for Arrange, Act and Assert. The method above that mocks an HttpContext is in the Arrange Part of our unit test. The creation of our View and our Presenter is also included in this part.

Arrange

So let's create those two:

Listing 8: Creating the View and the Presenter inside our Unit Test

Notice that we don't care about the actual implementation of the view and that is why we are mocking the interface. The view could easily be a WPF UserControl, a Silverlight UserControl etc. Testing if the view actually works falls into the area of Acceptance Tests.

Now that we have created our environment, our view and our presenter we have completed the first A – the Arrange part.

Act

The Act part is described in the following code snippet:

Listing 9: Act part of our Unit Test

Let's walk through those lines. First we create our model and set the appropriate values that correspond to our test case. Then we set the model to our view (which was created in the Arrange part) and next we use an extension method that is defined by RhinoMocks Framework and allows us to raise the Contacting event of our view.

What we expect is that the presenter has subscribed to that event, created the contact and change the ProcessState property of our model.

Assert

This is the final A of our Arrange-Act-Assert pattern. Is this unit test it's fairly simple

We expect the value of ProcessState property to be enProcessState.Saved.

Just for reference here is the entire Test file

Listing 10: ContactPresenterTests.cs

As you can see we are using [TestInitialize] attribute of Visual Studio Test Framework to initialize our Presenter and our View.

NOTE

Our Presenter is being initialized just before every test case.

Also when creating test methods many times is convenient to start with “Should” or “ShouldNot” based on if this method tests a valid scenario (example: user enters valid data and contact should be saved) or an invalid scenario (example: user enters invalid data and contact should not be saved).

Summary

This article was an introduction to testing a Web Application. You can download the code if this article and inside you will find a few extra goodies (which are out of scope of this article) like validating user's input, displaying messages across the application, using Attribute-based validation like MVC, Dependency Injection etc.

I hope this was a good kick-start on ASP.NET WebForms testing.

External libraries used:

<<  Previous Article Continue reading and see our next or previous articles Next Article >>

About John Katsiotis

John Katsiotis is a Microsoft MVP in ASP.NET since 2008 and .NET Developer for the past 4 years. You can find more info at his personal site or follow him on Twitter

This author has published 3 articles on DotNetSlackers. View other articles or the complete profile here.

Other articles in this category


Code First Approach using Entity Framework 4.1, Inversion of Control, Unity Framework, Repository and Unit of Work Patterns, and MVC3 Razor View
A detailed introduction about the code first approach using Entity Framework 4.1, Inversion of Contr...
jQuery Mobile ListView
In this article, we're going to look at what JQuery Mobile uses to represent lists, and how capable ...
Exception Handling and .Net (A practical approach)
Error Handling has always been crucial for an application in a number of ways. It may affect the exe...
JQuery Mobile Widgets Overview
An overview of widgets in jQuery Mobile.
Book Review: SignalR: Real-time Application Development
A book review of SignalR by Simone.

You might also be interested in the following related blog posts


Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 25: ViewModel read more
Updated SilverTwit Code for MSDN Magazine read more
Sneak Peek at our book Beginning ASP.NET MVC 1.0 read more
How do ASP.NET Application_ Events Work read more
Talking Points: ASP.NET Model-View-Controller (MVC) read more
Composite Application Guidance for WPF and Silverlight v2.0 (PRISM) read more
Provisioning a UCMA application using ApplicationProvisioner.exe read more
Six New Videos on ASP.NET Dynamic Data read more
URL Rewriting module for IIS 7 is live read more
Vista: RegisterApplicationRecoveryCallback read more
Top
 
 
 

Please login to rate or to leave a comment.