Testing WCF with Isolator – The Client

In my last post about testing WCF, I described how to easily test a server side component which is exposed by WCF. And obviously, the next step is to go to the client side. For this to work you don’t need configuration files, or any other definition. Isolator just needs type definition.

So here’s a consumer of my service:

public class DataProviderClient
{
ISourceListProvider channel;

public DataProviderClient()
{
RetrieveChannel();
}

private void RetrieveChannel()
{
ChannelFactory<ISourceListProvider> factory = GetFactory();
channel = factory.CreateChannel();
}

private ChannelFactory<ISourceListProvider> GetFactory()
{
EndpointAddress address = new EndpointAddress("http://AnyServer/service.svc");
WSHttpBinding binding = new WSHttpBinding();
return new ChannelFactory<ISourceListProvider>(binding, address);
}
    public string GetSourceListFromServer(string source)
{
string result;
try
{
result = channel.GetSourceList(source);
}
catch (CommunicationException)
{
return "Error";
}
if (result == string.Empty )
throw new ArgumentException("Bad Result");
return result;
}
}

The client, at construction, connects to the service, and at the GetSourceListServer, calls it, and performs a simple logic to see if the result has any meaning.

Note the code is refactored a bit. I could go on and fake all the nasty little WCF objects, but by extracting them into a single method, I just fake this method, making my life easier, and my tests more readable, and less fragile.

Let’s start with a simple test – fake the channel, and verify that the correct argument was sent to the server:

[TestMethod]
[Isolated]
public void FakeChannel_VerifyThatCallToChannelOccurs()
{
ISourceListProvider sourceListProvider = Isolate.Fake.Instance<ISourceListProvider>();
Isolate.WhenCalled(()=>sourceListProvider.GetSourceList ("AnyValue")).WillReturn("<XML></XML>");

SetupFakeChannelFactory(sourceListProvider);

DataProviderClient client = new DataProviderClient();
client.GetSourceListServer("MySource");

Isolate.Verify.WasCalledWithExactArguments(()=> sourceListProvider.GetSourceList("MySource"));
}

And the SetupFakeChannelFactory private method looks like that:

private void SetupFakeChannelFactory(ISourceListProvider provider)
{
ChannelFactory<ISourceListProvider> fakeFactory = Isolate.Fake.Instance<ChannelFactory<ISourceListProvider>>();
Isolate.SwapNextInstance<ChannelFactory<ISourceListProvider>>().With(fakeFactory);
Isolate.WhenCalled(()=>fakeFactory.CreateChannel()).WillReturn(provider);
}

The SwapNextInstance replaces the Swap method (based on customer feedback, who found this clearer), but does exactly the same: It sets up the fakeFactory to be swapped with the next instance of this type that will be created (this will happen inside the client’s constructor). The next line sets a return value as the provider. Note that our provider is not a concrete type – it’s a fake interface, representing our service.

I can of course test what happens when an incorrect result is returned from the server (I expect an exception in this case):

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
[Isolated]
public void FakeChannel_SimulateEmptyReturn()
{
ISourceListProvider sourceListProvider = Isolate.Fake.Instance<ISourceListProvider>();
Isolate.WhenCalled(()=>sourceListProvider.GetSourceList("AnyValue")).WillReturn(string.Empty);

SetupFakeChannelFactory(sourceListProvider);

DataProviderClient client = new DataProviderClient();
client.GetSourceListServer("MySource");
}

But if I want to test that something occurred on the wire, I can inject a CommunicationException (which causes an “Error” to be returned):

[TestMethod]
[Isolated]
public void GetSourceListFromServer_SimulateCommunicationException_ReturnError()
{
ISourceListProvider sourceListProvider = Isolate.Fake.Instance<ISourceListProvider>();
Isolate.WhenCalled(()=>
sourceListProvider.GetSourceList("AnyValue"))
.WillThrow(new CommunicationException());

InjectFakeProviderIntoFactory(sourceListProvider);

DataProviderClient client = new DataProviderClient();
string result = client.GetSourceListFromServer("");

Assert.AreEqual("Error", result);
}

So there you go, WCF simply isolated. Now you can test your logic around it, no excuses.

TOP