visargashi.com

Mocking a Data Access Component

December 04, 2012

The need for mocking dependencies while unit testing is, I hope, common knowledge. I won’t therefore spend any time covering mocking as a concept. What I want to propose in this article is a mocking technique that allows you to validate the state of the mocked database after test executes, as opposed to simply checking whether DAC operations are executed.

Data Access Component Model

Let's assume we are writing an application that manages blog posts, so we'll start with a Post domain object contract:
public class IPost
{
    int PostId { get; set; }
    string Title { get; set; }
    string Body { get; set; }
}
Next let's define a simple DAC contract that defines CRUD operations:
public interface IPostDac
{
    IPost Create(IPost post);
    IList Retrieve(int postId);
    IPost Update(IPost post);
    bool Delete(IPost post);
}
Note that both the domain object and the DAC contracts are simplistic but contain enough functionality for the mocking demonstration.

Rhino Mocks

I have selected Rhino Mocks for this article simply for convenience, many mocking frameworks can perform the functionality covered, I don't intend to discuss the merits of one framework over the other.

We are going to focus on mocking the “Create” operation, expanding the concept to the other operations should be trivial.

In a typical mocking implementation, we would see something similar to the following:

var repository = new MockRepository();
// Stub out a post object based on the post contract
var post = MockRepository.GenerateStub<IPost>();
// populate the post object
// ...

// Mock the DAC based on the defind contract
var postDac = MockRepository.GenerateMock<IDac>();
// Stub out the create operation to return our expected post object, regardless of the input
postDac.Stub(x => x.Create(Arg<IPost>.Is.Anything)).Return(post);

// ... perform the tests ...

// Verify the Create function was called
repository.AssertWasCalled(...);

Mocking the Database, Not Just the Operation

Having the ability to test the state of the Database after the test execution is more valuable, especially in scenarios when the DAC is being used by a component that performs multiple changes per execution.

First let’s define a Mock database inside the Test class using a simple List:

public IList<IPost> MockDatabase { get; set; }

Next, we’ll define a Create operation Delegate and a mock implementation:

public delegate IPost CreateDelegate(IPost post);
public IPost Create(IPost post)
{
    // Assign an id based on the database count
    post.PostId = MockDatabase.Count + 1;
    MockDatabase.Add(post);
    return post;
}

Finally, stub out the create operation using the previously defined delegate:

var repository = new MockRepository();
var mockDac = repository.StrictMock<IPostDac>();
mockDac.Stub(dac => dac.Create((IPost)null)).IgnoreArguments().Repeat.Any().Do((CreateDelegate)Create);

Now our test can be implemented as follows:

[TestMethod]
public void SavePostTest()
{
    var repository = new MockRepository();
    var mockDac = repository.StrictMock<IPostDac>();
    mockDac.Stub(dac => dac.Create((IPost)null)).IgnoreArguments().Repeat.Any().Do((CreateDelegate)Create);

    // ... this is where we would call the component that consumes the DAC
    //     and expect that it will call the IPostDac.Create operation
    //     but instead of checking whether the "Create" operation was executed, we are instead going to look at 
    //     the state of our mocked database

    // Expect one post to exist in the database
    Assert.AreEqual(1, MockDatabase.Count);
}

Conclusion and Next Steps

In this article I have proposed a DAC mocking approach that allows you to validate the state of the mocked database after the operation is complete. The code samples above should be enough to give you the idea, but for this solution to be practical, you will want to consider creating a mocker help class otherwise you will end up with much redundant code in all of your tests.

Start with defining the basis for your domain objects and data access components:

///<summary> 
/// Domain object definition 
/// </summary>
public interface IDomainObject 
{ 
    int Id { get; set; } 
} 
///<summary> 
/// Data access component definition 
/// </summary>
public interface IDac<T> where T : IDomainObject 
{ 
    T Create(T entity); 
    IList<T> Retrieve(int entityId); 
    T Update(T entity); 
    bool Delete(T entity); 
}

Then define your DAC mocker class:

public abstract class DacMocker<T, Y>
        where T : class, IDomainObject
        where Y : class, IDac
    {
        protected MockRepository Repository { get; set; }
        ///<summary> 
        /// Mock database 
        /// </summary>
        public IList<T> MockDatabase { get; protected set; } 
        ///<summary> 
        /// Mock data provider (uses the mock database) 
        /// </summary>
        public Y MockDac { get; protected set; } 
        public DacMocker(IListmockDatabase) 
        { 
            MockDatabase = mockDatabase; 
        } 

        public void CreateMock() 
        { 
            Repository = new MockRepository(); 
            MockDac = Repository.StrictMock<IDac>(); 
            // Stub out the create operation to return our expected post object, regardless of the input                         
            MockDac.Stub(dac => dac.Create((T)null)).IgnoreArguments().Repeat.Any().Do((CreateDelegate)Create); 
            // ... repeat for other operations 
        } 

        public delegate T CreateDelegate(T entity); 
        protected T Create(T entity) 
        { 
            // Assign an id based on the database count 
            entity.Id = MockDatabase.Count + 1; 
            MockDatabase.Add(entity); 
            return entity; 
        } 

        // ... repeat with delegate/operation implementation for other operations 
}

Written by Visar Gashi