Writing WCF Integration Tests
Prerequisites
This article covers creating a new WCF Service project, and creating integration tests leveraging the IISExpressify NuGet package.
- Install Software
- Ensure that Development activities > Windows Communication Foundations is installed
- Any edition should work for this, and Community Edition is free!
Verify installed templates
Open Visual Studio, and choose File > New > Project
WCF Service Application
For the simplicity of testing we can leverage the Visual Studio template for
creating a new WCF Service Application project. The template creates a service,
contract and several operations completely implemented. Create a new project
using the template; I named mine the default WcfService1
.
Configuring for HTTPS
The default configuration that is generated for the project exposes a
BasicHttpBinding
over http. Since I’m building an internet enabled application,
I want to change it to run on https. This is done with two elements <bindings>
and <services>
, which both live under the <system.serviceModel>
element as
child nodes.
The <bindings>
element describes all of the available bindings for the project.
We can create a new https enabled binding with the following xml:
<bindings>
<basicHttpBinding>
<binding name="https">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
The <services>
element describes which services use which bindings. For our
project we only have one binding and one service, so it is simple:
<services>
<service name="WcfService1.Service1">
<endpoint binding="basicHttpBinding" bindingConfiguration="https" name="httpsService1" contract="WcfService1.IService1" />
</service>
</services>
By default IIS Express is going to run under http, so we’ll need to adjust to
also serve https. Open up the properties window for the project, and set SSL
Enabled
to true.
Running a manual test
Visual Studio has a pretty slick test application that allows you to call
various operations called WCF Test Client. If you start the debugger while
Service1.svc.cs
is opened, then Visual Studio will automatically start the WCF
Test Client.
Error - Failed to add a service
Once the debugger has started the WCF Test Client may display an error Failed to add a service, and provides a detailed message that starts with Error: Cannot obtain Metadata from….
To resolve this, ensure that SSL Enabled
is set to true
for the WcfService1
project.
Error - Test Client isn’t open
After launching the debugger, Visual Studio will normally open a web browser
pointing to the web site. Visual Studio will only launch the WCF Test Client if
Service1.svc.cs
is open and focused.
Class Library
In order to share the service contracts between the service application, and the integration tests we need to create a new Class Library. Create a new Class Library for the solution; I named this WcfService1.Core.
Fortunately the WCF Service Application template puts all of the service
contract types into one code file: IService1.cs. Move this file from the
WcfService1
project to WcfService1.Core.
Lastly add a new project reference on WcfService1
that to reference the newly
created Class Library: WcfService1.Core.
xUnit Test Project Create the test project
In order to create an integration test, we can use the IISExpressifyhttps://www.nuget.org/packages/IISExpressify) package to host the WCF Services in IIS Express. We can encapsulate it within a Test Fixture for xUnit so we don’t need to launch IIS Express for every test method.
public class IisFixture : IDisposable {
static string GetHostingDirectory() =>
new DirectoryInfo(
Path.Combine(
Environment.CurrentDirectory,
@"..\..\..\..\..\src\WcfService1"
)
).FullName;
readonly IisExpress _iisExpress;
public IisFixture() =>
_iisExpress = IisExpress.Https()
.PhysicalPath(GetHostingDirectory())
.Port(44300)
.HideSystray()
.Start();
public void Dispose() => _iisExpress.Dispose();
}
[CollectionDefinition("IIS")]
public class IisCollection : ICollectionFixture<IisFixture> { }
In order to make sure that we use the same instance of IisExpress
for our
tests, we need to decorate our test class with the CollectionAttribute.
[Collection("IIS")]
public class IntegrationTest1 {
readonly IisFixture _iisFixture;
public IntegrationTest1(IisFixture iisFixture) => _iisFixture = iisFixture;
- I created some helper classes, which can be found on GitHub
- IisExpressExtensions.cs, WcfClient.cs and WcfClientBuilder.cs. Add these files to the project.
Now we can build our first test by integrating with the WCF Service contracts:
[Fact]
public void GetData_ShouldEchoInputValue()
{
var value = 123;
var expected = $"You entered: {value}";
var actual = _iisFixture.WcfClient<IService1>("Service1.svc")
.BasicHttpClient()
.Use(svc => svc.GetData(value));
Assert.Equal(expected, actual);
}
Once the test is in there, we can build and run the unit tests.
Wrapping it up
We created a new WCF service, shared its interface and built integration tests using IIS Express. You can extend the project further by integrating your own WCF services.
For some additional details check out this article’s complete implementation on GitHub. For the detailed steps check out the repository’s commit history.