views:

34

answers:

1

I have a WCF service that exposes 1 method GetNextObjectInList(int id) which hits a DB.

The WCF service works, more or less, like this:

public class MyService : IDisposable
{
    public MyService() 
    { 
        this.IntializeDBConnection();
    }

    public int GetNextObjectInList(int id) 
    { 
        /* uses DB connection */ 
    }

    /* Dispose releases DB connection */
}

This makes the client code relatively simple:

public void UseNextElementInList()
{
    IMyService svc = new MyServiceClient();
    int nextID = svc.GetNextObjectInList(this.ID);

    /* use object */
}

I've written unit tests to test the WCF services objects, but I'd like to test the consumer code for various things like timing/performance/error handling but I don't know how to construct my tests such that the Service doesn't hit the DB.

Most of my tests (the tests that run against the service's objects for instance) DO create an in-memory DB but I don't know how to get the service to connect to that without test-specific code in the service.

+1  A: 

I would create a test service for your unit tests. Typically what I do in these circumstances is create a config for the test project that is identical to the real one except the address would be local host, and the type would be my test service class:

        <service name="MyNamespace.TestService" behaviorConfiguration="BehaviorConfig">
            <endpoint address="net.tcp://localhost/MySolution/TestService"
                                binding="netTcpBinding"
                                bindingConfiguration="BindingConfig"
                                contract="MyNamespace.IMyService"/>

If you are using VS Test Project you can use the ClassInitialize / ClassCleanup attributes to set up / tear down the service:

    [ClassInitialize()]
    public static void MyClassInitialize(TestContext testContext) {
        mHost = new ServiceHost(typeof(TestService));
        mHost.Open();
        return;
    }
    [ClassCleanup()]
    public static void MyClassCleanup() {
        if(mHost != null) {
            mHost.Close();
        }
        return;
    }

Now inside of the TestService class (which would implement IMyService) you could provide whatever behavior necessary to test the client without worrying about your unit tests corrupting your production code

Steve Ellinger
+1: This looks very promising. Do you abstract out logic from the actual service so that both it and the test service call the same underlying logic?
SnOrfus
Only if I really have to. Keep in mind, in this scenario I'm not testing the service, I'm testing the client. This means that from a unit test point of view the situation is client sends data to service and the service should respond this way. In this case you are not necessarily doing the same processing in the service because it may not be necessary to test the client code.
Steve Ellinger
+1: I think we're on the same page. Thanks for your help Steve.
SnOrfus