Mocking without a mocking framework

I have not yet had the opportunity to use a proper mocking framework. My project has a future investigation into them, but it’s a low priority. However we are using Test Driven Development, so we have started using mocks (with dependency injection), so far the mocks have been statically defined and we are ‘learning as we go’ in the sense that the quality of the mock is changing as is our technique for creating them. We started off with a mock of a database with hard coded data in it, if you like we were replicating a simple set of data that the mock would interrogate. Over time this became very messy and was difficult to change for a specific test as you could break an existing test. The next approach was to remove all hard coded data and provide a mock that could be dynamically loaded with data by the test. This seems better (and more like how mocking frameworks work I believe). However recently I realised the method for loading data was flawed as if a class called the same method twice, but required different output on each call then the mock would not be able to provide this. The following shows my current thinking for how to define a bespoke mock with dynamically loaded data. Using a queue to load the data for each call.

  1. Create your mock implementing the mocked object(s) interface(s)
  2. Create a field/property of type queue<type> for each type of data that needs to be returned
  3. Create a constructor for the mock that news all the queues
  4. For each method on the interface(s) take the appropriate queue and Dequeue() an item from it
public class MockDB:ICustomerDataAccess
{
    #region Dynamically loaded results
    private Queue<List<Customer>> loadedCustomerListQueue;
    public Queue<List<Customer>> LoadedCustomerListQueue
    {
        get { return loadedCustomerListQueue; }
        set { loadedCustomerListQueue = value;}
    }
    private Queue<Customer> loadedCustomerQueue;
    public Queue<Customer> LoadedCustomerQueue
    {
        get { return loadedCustomerQueue; }
        set { loadedCustomerQueue = value; }
    }
    #endregion
    public MockDB2()
    {
       LoadedCustomerListQueue = new Queue<List<Customer>>();
       LoadedCustomerQueue = new Queue<Customer>();
    }
    #region ICustomerDataAccess Members
    public List<Customer> GetCustomerByForeignKey(long ID)
    {
        return LoadedCustomerListQueue.Dequeue();
    }
    public Customer GetCustomerById(long id)
    {
        return LoadedCustomerQueue.Dequeue();
    }
    #endregion
}

To use the mock in a test:

  1. Create an instance of the mock
  2. Enqueue items into the appropriate queue in the order that they should be returned in the tested class.
[TestMethod()]
[ExpectedException(typeof(CustomerMaintenanceException))]
public void UpdateCustomer_DoesntExist_Fail()
{
    MockDB Mock= new MockDB();
    UpdateCustomer target = new UpdateCustomer(Mock);
    Customer NonExistant=new Customer();
    Mock.LoadedCustomerQueue.Enqueue(null);
    target.Execute(NonExistant);
}

Some points to note:

  • You can enqueue null values onto a queue
  • You can have a queue of lists
  • This only works if the tested class has a predictable logic flow, but for a proper unit test this should always(?) be the case
  • This is not meant to be better or even anywhere near as good as a mocking framework, but where you can’t use a framework this approach seems sensible

Update: As my knowledge of mocking has improved I have realised that this is not really mocking, rather a sort of dynamic stubbing (see this post)

Advertisements

About Alex McMahon

I am a software developer, interested in .net, agile, alt.net. I've previously specialised with .net 3.0 technologies like WCF, whereas now I am trying to specialise in agile development and best practice and patterns. I am obsessed with looking at the latest technologies, tools, and methods, and trying them out. I am currently employed by Rockwell Collins in the UK.
This entry was posted in dependency injection, development, IoC, methodology, mocks, TDD, techniques, testing. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s