Writing WCF Integration Tests

Prerequisites

This article covers creating a new WCF Service project, and creating integration tests leveraging the IISExpressify NuGet package.

  1. Install Software
  • Visual Studio 2017
    • 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
2018-06-08-07_34_20-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.
2018-06-08-09_05_07-WcfService1---Microsoft-Visual-Studio

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.
2018-06-08-09_09_25-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 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.
2018-06-08-09_38_05-WcfService1---Microsoft-Visual-Studio

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.