This post is geared towards ADO.NET Data Services but the techniques used here could really be used to perform integration testing for any WCF service.
First off, yes, I realize that you can test the vast majority of your service functionality outside of an actual service -- after all, there’s no reason for us to test the networking code somebody at Microsoft wrote. But lets assume that, for some reason, you wanted to perform a full-blown integration test for your ADO.NET Data Service. How can we do it? A few notes to get started:
1) The service needs to start before any tests execute. We can accomplish this by using the TestFixtureSetup attribute in NUnit.
2) The service needs to run in its own thread. This is because it will service requests that originate from tests in the same test fixture. NUnit executes all methods within the fixture synchronously. If the service started and blocked while waiting for requests then that would be a very bad thing – as the test run would never complete and no tests would be executed.
3) The service needs to handle requests for the lifetime of the test fixture and no longer. We can make this happen by using an AutoResetEvent instance. This will cause the thread that’s hosting the service to block until it receives a signal. We can initiate this signal from a method that is adorned with the TestFixtureTeardown attribute. NUnit executes all methods with this attribute after it executes all methods adorned with the "Test attribute. This will allow the service to close and dispose of itself.
private static readonly Uri serviceUri = new Uri("http://localhost:1642/MyService.svc");
private static AutoResetEvent serviceResetEvent = new AutoResetEvent(false);
[TestFixtureSetUp]
public void FixtureSetup()
{
Action runService = () =>
{
using (var host = new WebServiceHost(typeof(MyService), serviceUri))
{
host.Open();
serviceResetEvent.WaitOne();
host.Close();
}
};
var thread = new Thread(new ThreadStart(runService));
thread.Start();
}
The key thing to notice here is that the AutoResetEvent instance starts with its initial state == false. This will cause calls to the “WaitOne” method to block until a signal is sent using the “Set” method – which is exactly what we need to do in the test fixture tear down operation:
[TestFixtureTearDown]
public void FixtureTearDown()
{
serviceResetEvent.Set();
}
We can now create integration tests that actually call the Data Service. A simple example might be:
[Test]
[Category("Integration")]
public void DataServiceIntegrationTestExample()
{
DataServiceContext context = new DataServiceContext(serviceUri);
DataServiceQuery query =
context.CreateQuery< MyType >("MyMethod")
.AddQueryOption("someParameter", "'someValue'");
var results = context.Execute< MyType >(query.RequestUri);
Assert.IsTrue(results.Count< MyType >() == 1);
}
This will create a WCF service request which will get served by the service instance created in the test fixture setup method.