There's a lot of info out there on how to cobble together NUnit Unit Testing of ASP.NET
Pages and assorted goo. NUnitASP is
a nice class library to facilitate this kind of testing, but it doesn't solve a few
Do you have/want a Web Server on your Test/Build machine?
How do you get your Test Pages and such over to the Web Server? Just automatically
Are your Test cases self-contained? That is, do they require external files and other
stuff to be carried along with them?
I have a need to test a number of utility classes, base classes for System.Web.UI.Page
and other miscellany and I'd like the tests to be entirely self contained and runnable
only with NUnit as a requirement.
So, here's a small solution we use at Corillian. I use Cassini,
the tiny ASP.NET Web Server that brokers HTTP Requests to System.Web.Hosting
and the ASP.NET Page Renderer. You may know Cassini as the precursor to the Visual
Developer Web Server from Visual Studio "Whidbey" 2005. Cassini usually comes with
two parts, CassiniWebServer.exe and Cassini.dll. However, I don't want to launch
a executables, so I'll just refer to Cassini.dll as that is the main engine.
Cassini is the 'private Server webServer' in the code above. I'm using a fairly random
port, but you could certainly scan for an open port if you like. Note that I'm building
a /bin folder, as Cassini's own ASP.NET Hostingn AppDomain will look for DLLs to load
Cassini starts up another AppDomain, and that AppDomain then loads Cassini.dll AGAIN,
except the new AppDomain has a different search path that includes /bin, so it won't
find Cassini.dll in the current directory. Usually this problem is solved by putting
Cassini.dll in the GAC, but I want this test to be self-contained, and since I'll
need my other DLLs in /bin anyway...
public void Setup()
//Extract the web.config
and test cases (case sensitive!)
//NOTE: Cassini is going
to load itself AGAIN into another AppDomain,
// and will be getting
it's Assembliesfrom the BIN, including another copy of itself!
// Therefore we need
to do this step FIRST because I've removed Cassini from the GAC
//Copy our assemblies
down into the web server's BIN folder
foreach(string file in Directory.GetFiles(tempPath,"*.dll"))
Additionally, I've snuck a new method in, ExtractResource(). This takes the name of
an Embedded Resource (one that is INSIDE our test assembly) and puts it into a directory.
In this case, I'm using the current AppDomain's directory, but you could certainly
use Path.GetTempPath() if you like.
private StringCollection extractedFilesToCleanup
= new StringCollection();
infile = new StreamReader(stream))
The ExtractResource method takes a filename and directory (and could, if you like,
take a namespace, although I've hardcoded mine) and pulls a file as a Stream of bytes
that was embedded as a resource in our Assembly and puts it into a directory. Hence
the name, ExtractResource(). There is a StringCollection called extractedFilesToCleanup
that keeps track of all the files we'll want to delete at the end of these tests,
At this point, I've got a web.config (which was important to my tests, and will be
looked at by Cassini/System.Web.Hosting) and a test1.aspx and test2.aspx in my current
directory. The Cassini Web Server is started up and listing on port 8085 for HttpRequests.
I also turned Page Tracing on in the web.config which will allow me to make certain
Assertions about what kinds of code were called by the Page and helper classes within
the Cassini ASP.NET context.
I'll add a helper method to create HttpRequests and return the response as a string:
private string GetPage(string page)
WebClient client = new WebClient();
= new Uri(new Uri(webServerUrl),page).ToString();
reader = new StreamReader(client.OpenRead(url)))
Now I can write some tests! My tests need to test things like the overridden behavior
of custom BasePages (derived from System.Web.UI.Page) as well as some helper functions
that require (to be TRULY tested) an HttpContext. However, I don't want the hassle
of a CodeBehind or a lot of other files, and certainly not the effort of a whole
separate test project, so I'll make my ASPX pages self contained using <%
@Assembly %> directives. So, for example:
A test to determine if this page executed successfully might look like:
public void BasicSmokeTestOfWebServer()
Assert.IsTrue(result.IndexOf("Hello") != -1,"Basic smoke
test of test1.aspx didn't find 'Hello' in response!");
You could easily expand your tests to include NUnitASP, or
continue to use WebClient with specific HttpHeaders like accept-language or user-agent.
One of our QA guys uses NUnit to automate the IE WebServer Control, the
manipulates the DHTML DOM to make Assertions.
Finally, my cleanup code is simple, deleting all the files we extracted as well as
toasting the /bin folder.
public void TearDown()
webServer = null;
private void CleanupResources()
foreach(string file in extractedFilesToCleanup)
Now the WebServer, Test Cases and Test are nicely self-contained and can be moved
to the CruiseControl.NET Continuous Integration Build Server.