A pattern for unit testable Asp.net pages: Part 1

I previously blogged about the pattern we used in our WPF application to separate business logic from the presentation, making the business logic view and data models highly unit testable. Now that I’m working on Asp.net code for Live Folders, we’ve worked to come up with a similar model that separates the business logic from the presentation. The model we use may not apply to everyone, but I thought I’d present it in a series of posts to hopefully help people out and to get some good feedback.

Live Folders is a pretty basic (Web 1.0!) type application that doesn’t make heavy use of client-side JavaScript. It also doesn’t use view state or any of the complex Asp.net controls. If your application model is significantly different, this pattern may not work for you.

This pattern breaks a page into two parts. The PageModel is the unit testable business logic for the page, which has no Asp.net dependencies. Then, there’s the Page subclass, which collects data about the request (query parameters, form post values, etc), runs the model, and then binds data from the model into its controls. The Page subclass is not unit testable because of its Asp.net dependencies (the Asp.net code should tested with scenario tests that automate the browser).

The PageModel may need to do things like redirect the user or throw a page not found error. These sorts of Asp.net dependencies are abstracted out with an interface called IPageContext. A mock implementation is used for unit testing, and an Asp.net specific implementation is used in the real pages.

This series will consist of the following parts:

Part 2: The core classes (PageModel, PageModelBasedPage, IPageContext)

Part 3: An example

Part 4: Unit testing the example

The resulting code is available at http://folders.live.com/self.aspx/+drExD6aaB0/Blog/PageModelPattern.zip.

Comments (2)

  1. .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New",

  2. .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New"