Welcome to Dovetail Software Blogs : Sign in | Join | Help
Unit Testing a Web Service

Dovetail sells a web services for Clarify product that consists of a SOAP flavored web service and a handy client library. To make sure all is continuously well we have NUnit integration tests that exercise the client library making calls against the web service. Our first iteration of the testing the web service involved launching Cassini and then later the development web server that comes with Visual Studio 2005 to host our web service under test. The configuring and launching of this process (WebDev.WebServer2.exe) has  been fragile and prone to failure. Yesterday while setting up a new integration server I flailed for an hour trying to get the web server running. My defeat turned into victory after I found Phil Haack's post on Using WebServer.WebDev For Unit Tests which taught me how remove our dependency on the executable web server and instead use the underlying assembly WebDev.WebHost.dll to do all the heavy lifting in-process with our tests.

Using Phil's guidance: I grabbed the web host assembly out of the GAC and threw it into our lib folder then I was able to do a little hacking to Phil's TestWebServer.cs. It was pretty easy to adapt it to get a web server started and hosting our web application. Here is the meat of what the class does.

1 public Uri Start() 2 { 3 //NOTE: WebServer.WebHost is going to load itself AGAIN into another AppDomain 4 //NOTE: so we need to make sure that it is present in the binaries for the web application. 5 File.Copy("WebDev.WebHost.dll", Path.Combine(_webRootDirectory, @"bin\WebDev.WebHost.dll"), true); 6 7 //Start the internal Web Server pointing to our test webroot 8 _webServer = new Server(_webServerPort, _webServerVDir, _webRootDirectory); 9 webServerUrl = String.Format("http://localhost:{0}{1}", 10 _webServerPort, _webServerVDir); 11 12 _webServer.Start(); 13 started = true; 14 Debug.WriteLine(String.Format("Web Server started on port {0} with VDir {1} in physical directory {2}", 15 _webServerPort, _webServerVDir, _webRootDirectory)); 16 return new Uri(webServerUrl); 17 }

Once I got the TestWebServer class working for my needs it was easy to update our test fixture. I created a test fixture base class to handle starting the web server and configuring the client to the web service.

1 [TestFixture] 2 public class WebservicesTest : ClarifyBaseTest 3 { 4 private TestWebServer _webServer; 5 private ClarifyApplicationWS _clarifyApplicationWS; 6 7 public ClarifyApplicationWS ClarifyApplicationWS 8 { 9 get { return _clarifyApplicationWS; } 10 } 11 12 protected override void OnTestFixtureSetup() 13 { 14 string webRootDirectory = ConfigurationManager.AppSettings["ClarifyWebServices.root.dir"]; 15 _webServer = new TestWebServer(webRootDirectory); 16 17 Uri serverUrl = _webServer.Start(); 18 _clarifyApplicationWS = new ClarifyApplicationWS(serverUrl.AbsoluteUri); 19 } 20 21 protected override void OnTestFixtureTeardown() 22 { 23 if (_webServer != null) 24 { 25 _webServer.Stop(); 26 } 27 } 28 }

Now all the tests run without needing to launch a web server. Life is good. I went over to the integration server did an svn update and all web service tests ran without further complication. Decoupling our build from the complexity of launching a separate process feels great. Thank you Phil for the excellent and informative post (Subscribed).

Posted: Wednesday, November 07, 2007 11:41 AM by kmiller
Filed under: ,

Comments

Ray Houston said:

That's awesome Kevin!

# November 17, 2007 5:46 PM

Bill Sorensen said:

I'm afraid this isn't working for me. I always get "An unhandled System.AppDomainUnloadedException was thrown while executing this test : Attempted to access an unloaded AppDomain."

Another poster reported something similar on Phil's site, but they would only get the error on a second test; I get it on the first web method access.

Any suggestions?

Thank you!

# December 6, 2007 11:35 AM

kmiller said:

@Ray: Thanks!

@Bill:

I sent you the full TestWebService.cs to your blog. I hope it helps. You need to make sure your .asmx files and assemblies are present in the bin directory.

It is also important that the WebDev.WebHost.dll be present in your web service application bin directory. It should be copied there by Start().  

# December 6, 2007 11:59 AM

Bill Sorensen said:

Thank you very much! :-)

# December 7, 2007 10:50 AM