Showing posts with label dependency. Show all posts
Showing posts with label dependency. Show all posts

Wednesday, July 14, 2010

Unit testing, how do I unit test a Singleton?

Well, as with our WebService client sample, this question is a misnomer. More often than not we are interested in unit testing consumers of a Singleton than unit testing a Singleton's functional set - and depending on implementation, this may not be as straightforward as we think.

Consider

// a fairly typical Data Access Layer implementation (DAL). have actually
// encountered this on-site [shudders].
public static class DatabaseConnectionFactory
{
    public static IDbConnection GetDatabaseConnection ()
    {
        // 1. get connection string from config
        string connectionString = null;

        // 2. create connection
        SqlConnection connection = null;
        connection = new SqlConnection (connectionString);
        connection.Open ();

        // 3. some other custom stuff
        // 4. return connection
        return connection;
    }

    public static IDbCommand GetDatabaseCommand (
        string commandString,
        IDbConnection connection)
    {
        // 1. set custom stuff like transaction and timeout
        // 2. return command
        return new SqlCommand (commandString, connection);
    }
}

// embedded DAL logic in business tier - anyone else vomit in their 
// mouth just a little? - however what is especially offensive is the
// direct calls to data tier via static class DatabaseConnectionFactory
public class AppointmentBusinessObject
{
    public const string CommandString_LoadById_OneParameter = 
@"SELECT * 
FROM Appointments 
WHERE AppointmentId = {0}";

    public void LoadById (long appointmentId)
    {
        // 1. create Sql command string,
        string commandString = 
            string.Format (
            CommandString_LoadById_OneParameter,
            appointmentId);

        try
        {
            // 2. get connection,
            IDbConnection connection = 
                DatabaseConnectionFactory.
                GetDatabaseConnection ();

            // 3. get command,
            IDbCommand command = 
                DatabaseConnectionFactory.
                GetDatabaseCommand (commandString, connection);

            // 4. execute command
            Reader reader = command.ExecuteReader ();

            // 5. read contents
        }
        finally
        {
            // 6. close connection,
            if (connection != null) 
            {
                connection.Close ();
            }
        }

    }

}

Now, there are many reasons why this is a poor design, not the least of which is that we are locked into a single connection and a single implementation. We are forced to duplicate this source if any of these parameters need to change - and believe me this has happened!

If this were not reason enough to contemplate a complete revision, our ability to unit test is also impaired. Specifically, we cannot unit test or verify LoadById without hitting a datastore! In fact, we cannot unit test any class or method that invokes LoadById without hitting a datastore.

So what can we do?

Well the first thing to do is identify the actual problem - and here it appears to be a tight coupling between our business and data tiers. If we were to abstract DatabaseConnectionFactory then the result would be a loosely-coupled and more flexible system. To this end, I would suggest introducing an interface (that defines DatabaseConnectionFactory's existing members) and consuming this wherever possible.

For example,

// a simple data store interface, exposes full functional set
// of existing DatabaseConnectionFactory
public interface IDatabaseConnectionFactory
{
    IDbConnection GetDatabaseConnection ();
    IDbCommand GetDatabaseCommand (
        string commandString, 
        IDbConnection connection);
}

// we want this to be as low-impact as possible, so new
// interface defines members that already exist. sadly, 
// static classes cannot implement interfaces directly, 
// and so DatabaseConnectionFactory must be made an instance 
// class. while this requires a little deft maneuvering, 
// this may be accomplished with *zero* impact to existing 
// consumers! yay!
//
// 1. remove static key word from class declaration, this makes
// class instance-based
public class DatabaseConnectionFactory : IDbConnectionFactory
{

    // 2. remove static key word from members, this simply
    // makes existing method implementations instance-based
    public IDbConnection GetDatabaseConnection () { ... }
    public IDbCommand GetDatabaseCommand (
        string commandString,
        IDbConnection connection) { ... }

    // 3. define *new* static members that delegate to
    // instance-based members, this ensures that existing 
    // consumers do not break
    public static IDbConnection GetDatabaseConnection ()
    {
        // instantiate new factory every call for clarity,
        // potential optimization in declaring a static
        // lazy-loaded instance member, and delegating
        // to that instead
        DatabaseConnectionFactory factory = 
            new DatabaseConnectionFactory ();
        return factory.GetDatabaseConnection ();
    }
    public static IDbCommand GetDatabaseCommand (
        string commandString,
        IDbConnection connection) 
    {
        DatabaseConnectionFactory factory = 
            new DatabaseConnectionFactory ();
        return factory.GetDatabaseCommand (commandString, connection);
    }
}

// embedded DAL logic in business tier - vomitting just a little less -
// less offensive now we reference implementation-independent datastore
// definition
public class AppointmentBusinessObject
{
    // still tightly coupled to Sql-compliant datastore
    // but manageable.
    public const string CommandString_LoadById_OneParameter = 
@"SELECT * 
FROM Appointments 
WHERE AppointmentId = {0}";

    // 1. declare new factory member. this is our *dependency*
    // it *must* be fulfilled for class to operate successfully
    private readonly IDbConnectionFactory _factory = null;

    // 2. expose new parameter constructor, permitting consumers
    // of *this* class to specify an appropriate datastore
    public AppointmentBusinessObject (IDbConnectionFactory factory)
    {
        _factory = factory;
    }

    // 3. expose new parameterless constructor, this preserves
    // existing consumers who may not be "up to speed" regarding
    // this new-fangled connection specification. we also preserve
    // previous operating expectations by defaulting to ... 
    // "default" connection factory, so at worst, we deliver
    // *EXACTLY* same behaviour as before
    public AppointmentBusinessObject ()
        : this (new DatabaseConnectionFactory ())
    {
    }

    // 4. consume!
    public void LoadById (long appointmentId)
    {
        // ...
        try
        {
            IDbConnection connection = 
                _factory.GetDatabaseConnection ();
            IDbCommand command = 
                _factory.GetDatabaseCommand (commandString, connection);
            // ...
        }
        finally
        {
            // ...
        }
    }

}

So, where is the payoff exactly? Well, for one if we now wish to change datastore implementation (say to a MySql, or Oracle, or some other Sql-compliant datastore) we implement a new class and may swap between the two when desired. We also gain the ability to load objects from two or more datastores at the same time!

As a pleasant side-effect, we are also able to unit test LoadById directly, and any consumers that permit datastore specification.

// test business logic without hitting datastore! yay!
[TestMethod]
public void Test_LoadById ()
{
    IDbConnectionFactory mockFactory = null;
    // instantiate mock with expectations
    AppointmentBusinessObject appointment = 
        new AppointmentBusinessObject (mockFactory);
    appointment.LoadById (1024);
    // verify results
}

Friday, July 9, 2010

Unit testing, how do I unit test a WCF Service with dependency OperationContext?

Unit testing WCF Services is a lot like testing Web Services, especially in that they represent remote business logic. However, in some cases testing may not be straightforward, such as when referencing static framework class OperationContext,

// a simple subscription based service.
[ServiceContract (CallbackContract = typeof (ISubscriberCallback))]
public interface ISubscriptionService
{
    // push a subject to service
    [OperationContract]
    void Publish (string subject);

    // subscribe client to publications.
    [OperationContract]
    void Subscribe ();

    // unsubscribe client from publications.
    [OperationContract]
    void Unsubscribe ();
}

// a simple client-side subscription callback.
public interface ISubscriberCallback
{
    // push a subject to subscribers
    [OperationContract]
    void Receive (string subject);
}

// a possible implementation of subscription service
[ServiceBehavior (
    ConcurrencyMode = ConcurrencyMode.Multiple, 
    InstanceContextMode = InstanceContextMode.Single)]
public class SubscriptionService : ISubscriptionService
{

    private readonly object _syncRoot = new object ();
    private readonly List<ISubscriberCallback> _subscribers = 
        new List<ISubscriberCallback> ();

    public void Publish (string subject) { ... }

    public void Subscribe ()
    {
        // hm, static framework references ... 
        ISubscriberCallback subscriber = 
            OperationContext.
            Current.
            GetCallbackChannel<ISubscriberCallback> ();

        lock (_syncRoot)
        {
            if (!_subscribers.Contains (subscriber))
            {
                _subscribers.Add (subscriber);
            }
        }
    }

    public void Unsubscribe () { ... }

}

Unfortunately, if our service implements some sophisticated business logic while initializing callbacks then we risk either losing coverage with no tests or losing time and resources on elaborate environments to support our integration into WCF framework.

Well not to fear, this is strikingly familiar to our Web Service with Context dependency, and I would proscribe a similar solution. Namely,

// a simple abstraction to separate our business from 
// WCF framework. depending on our requirements, could be
// general for re-use elsewhere in our application code,
// or specific if this is a one-off use.
public interface IOperationContext
{
    // add methods as needed, for now we definitely
    // need access to our callbacks!
    CType GetCallbackChannel<CType> ();
}

// a simple wrapper implementation of operation context
public class OperationContextCurrent : IOperationContext
{
    public CType GetCallbackChannel<CType> ()
    {
        return OperationContext.
            Current.
            GetCallbackChannel<CType> ();
    }
}

[ServiceBehavior (
    ConcurrencyMode = ConcurrencyMode.Multiple, 
    InstanceContextMode = InstanceContextMode.Single)]
public class SubscriptionService : ISubscriptionService
{

    private readonly IOperationContext _context = null;
    private readonly object _syncRoot = new object ();
    private readonly List<ISubscriberCallback> _subscribers = 
        new List<ISubscriberCallback> ();

    // inject our dependency on operation context! this
    // decoupling actually makes sense - if we swap 
    // transport stacks we just require an implementation
    // that returns our requested callbacks!
    public SubscriptionService (IOperationContext context)
    {
        _context = context;
    }

    public void Subscribe ()
    {
        // ... ahhhh, that's much better!
        ISubscriberCallback subscriber = 
            _context.
            GetCallbackChannel<ISubscriberCallback> ();

        lock (_syncRoot)
        {
            if (!_subscribers.Contains (subscriber))
            {
                _subscribers.Add (subscriber);
            }
        }
    }

}

Now, if we were so inclined to test Subscribe above,

// test business logic without WCF! yay!
[TestMethod]
public void Test_Subscribe ()
{
    IOperationContext mockContext = null;
    // instantiate mock with expectations
    SubscriptionService service = new SubscriptionService (mockContext);
    service.Subscribe ();
    // verify results
}

Wednesday, April 7, 2010

Unit testing, how do I unit test WebService X with dependency Y?

Before moving on, I would like to build on our WebService example. In that example, we separated our business logic from our hosting solution. However, it may occur that our source solution has dependencies that must be fulfilled.

Consider this modified example,

// a profile web service, represents business logic 
// hosted from a web service
public class ProfileWebSevice : System.Web.Services.WebService
{

    // gets a profile for remote client
    [WebMethod]
    public Profile GetProfile (Session session)
    {
        Profile profile = null;

        // obtain authentication service from
        // web service context
        AuthenticationService auth = 
            (AuthenticationService)(Context.Cache["auth"]);

        // embedded business logic, bad bad bad
        // 
        // 1. authenticate
        if (auth.IsAuthenticated (session))
        {
            // 2. create sql connection
            // 3. get profile
            // 4. populate profile
            profile = new Profile (dataReader);
        }

        return profile;
    }

}

Note the dependency introduced by member variable Context. If we were to perform our simple refactor, we introduce compile-time issues,

public class ProfileService  
{ 
    public Profile GetProfile (Session session) 
    { 
        // COMPILE-ERROR: "Context" does not exist here! oh nos!!!
        AuthenticationService auth = 
            (AuthenticationService)(Context.Cache["auth"]);
        // ...
    } 
}

Fortunately, the solution is fairly straightforward. The key is realising our business logic of authenticate, fetch, instantiate is completely separate from the services that facilitate it. Our business class is a consumer of these services. From this perspective, it seems obvious to request these services as part of our invocation.

public class ProfileService  
{ 
    public Profile GetProfile (AuthenticationService auth, Session session) 
    {
        if (auth.IsAuthenticated (session)) { ... }
        // ...
    }
}

and our WebService now looks like

public class ProfileWebSevice : System.Web.Services.WebService
{
    [WebMethod]
    public Profile GetProfile (Session session)
    {
        AuthenticationService auth = 
            (AuthenticationService)(Context.Cache["auth"]);
        ProfileService service = new ProfileService ();
        Profile profile = service.GetProfile (auth, session);
        return profile;
    }
}

Again, our business logic does not care who or how a service is implemented, only that whomever is doing it, conforms to some known invocation. In this scenario, that an object instance of type AuthenticationService contains a method IsAuthenticated.

Our unit tests may look like

// test business logic without web service! yay! 
[TestMethod] 
public void Test_GetProfile_NullSession () 
{ 
    AuthenticationService auth = new AuthenticationService ();
    ProfileService service = new ProfileService (); 
    Profile actual = service.GetProfile (auth, null);
    // verify profile expectations
    // verify authentication service expectations
}