Posts
12
Comments
45
Trackbacks
0
Integration Testing WCF services with Unity

Previously I wrote an article regarding Unit Testing WCF with Unity. Unit testing allows you to test a single component of your application, completely independent of any other components or systems. Once you have successfully created your unit tests, the logical next step is to see how your service works when connected to other components. These integration tests allow you, for example, to run tests against your service and see how it behaves when writing to a database or consuming another service.

Integration Testing WCF services
To perform integration testing against a service, you have a few different options to go with; each with their own advantages and disadvantages:
  1. Utilize the Asp.Net web server (Cassini) within Visual Studio
  2. Deploy your service to IIS
  3. Setting up your service host and starting it from within the integration test environment

1. Use the Asp.Net web server in Visual Studio
This is the most convenient approach during the development phase, however you will have to remember to keep re-starting the development web server whenever it times out. You will also need to create a proxy class (using svcutil.exe or the service reference wizard in VS) as well as maintain the endpoint configuration for the service in your web.config or app.config file.

2. Deploy to IIS
This option allows you to test your service against IIS. A web application directory will need to be created (VS can do this for you) but unlike Cassini, you won't have to worry about the server timing out. This option isn't the best choice if you frequently test different services and will also leave you having to handle multiple web application directories lounging around IIS. Again, you will need to create a proxy class as well as have the service endpoint in your configuration file.

3. Create/start your service host "on the fly"
This is the "cleanest" approach and does not have any of the drawbacks of the first two options. The service is automatically created/started/stopped from within the test class setup/teardown code whenever you run your tests. Another advantage is that you can run your unit/integration tests automatically and unattended using the Build Server within TFS (Team Foundation Server).

Below is an example of how you would accomplish this:

   1:  [TestClass]
   2:  public class WcfIntegrationTests
   3:  {
   4:      private static ServiceHost svcHost;
   5:   
   6:      [ClassInitialize]
   7:      public static void TestClassInitialize(TestContext testContext)
   8:      {
   9:          svcHost = new ServiceHost(typeof(WcfService), new[] { new Uri("http://localhost/") });
  10:          svcHost.AddServiceEndpoint(typeof(IWcfService), new BasicHttpBinding(), "WcfService");
  11:          svcHost.Open();
  12:      }
  13:   
  14:      [ClassCleanup]
  15:      public static void TestClassCleanup()
  16:      {
  17:          svcHost.Close();
  18:      }
  19:   
  20:      [TestMethod]
  21:      public void GetUsers()
  22:      {
  23:          var endptaddr = new EndpointAddress("http://localhost/WcfService");
  24:          var Wcfproxy = ChannelFactory<IWcfService>.CreateChannel(new BasicHttpBinding(), endptaddr);
  25:          var result = Wcfproxy.GetUsers();
  26:          Assert.IsTrue(result.Count > 0, "No users found");
  27:      }
  28:  }


Now if your WCF service is utilizing an IoC container for unit testing by way of WCF extension points (see my previous post on Unit Testing WCF with Unity), you will notice right away that you receive the following error...

System.InvalidOperationException: The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor

The reason for this error is because of our ServiceHostFactory we created for our unit tests. The Factory doesn't have any available public methods to be able to create the service host from a given service type. What we will need to do is create a wrapper class for the factory and define a public method to create the service host and allow for a type to be passed in as a parameter.

   1:  private class WcfServiceHostFactoryWrapper : WcfSvcServiceHostFactory
   2:  {
   3:      public ServiceHost CreateServiceHost(Type serviceType, string baseAddress)
   4:      {
   5:          return CreateServiceHost(serviceType, new[] { new Uri(baseAddress) });
   6:      }
   7:  }
   8:   
   9:  [ClassInitialize]
  10:  public static void TestClassInitialize(TestContext testContext)
  11:  {
  12:      var serviceHostFactoryHarness = new WcfServiceHostFactoryWrapper();
  13:      svcHost = serviceHostFactoryHarness.CreateServiceHost(typeof(WcfService), "http://127.0.0.1/");
  14:      svcHost.AddServiceEndpoint(typeof(IWcfService), new BasicHttpBinding(), "WcfService");
  15:      svcHost.Open();
  16:  }


Now you can just select the test to run from the Visual Studio Test List Editor, or run unattended from the TFS Build Server, with no dependencies on IIS or configuration.

 

posted on Monday, December 21, 2009 12:46 PM Print
Comments
Gravatar
# re: Integration Testing WCF services with Unity
Svchost exe
11/14/2010 8:20 PM
I indeed receive that exact error, thanks a lot for the fix. :)

Post Comment

Title *
Name *
Email
Comment *  
Verification
Coding strategies for the Java and .Net developer...