There are some pretty good Mock object frameworks available out there for .net like NMock, EasyMock, TypeMock, etc... But I think every one will ultimately wind up using Rhino Mock at the end because of its easy to grasp rich feature set. So lets see how we can use Rhino to to mock a layered architecture for unit testing purposes.

I will try to mock the repository and the service layer in the following code in an easy to understand manner

Here are my sample repository and service interfaces (I have used NHibernate and Windsor Castle in this project as the ORM solutionl)

Repository Interface

 public interface IInventoryRepository : IRepository
    {
        List<RecordItem> Get(List<int> ids);
        List<RecordItem> Get(List<int> ids, string orderByColumn, string orderType);
    }


Service Interface

public interface IInventoryService  
    {
        List<ServiceItem> Get(List<int> ids, int truncLength);
        List<ServiceItem> Get(List<int> ids, string orderByColumn, string orderType, int truncLength);
    }

As I have described in my previous post lest use Nbuilder to mock the test objects that needs to be returned when the methods in the repository are called

Mock return for List<RecordItem> Get(List<int> ids)
private static List<RecordItem> CreateRecordItems()
        {
            var items = Builder<RecordItem>.CreateListOfSize(10).WhereAll().Have(x => x.Title = "sample title").WhereAll().Have(x => x.AuthorName = "Dhanushka").Build().ToList();
            for (int i = 1; i < items.Count + 1; i++)
            {
                EntityIdSetter.SetIdOf(items[i - 1], i);
            }
            return items;
        }

Mock return for List<RecordItem> Get(List<int> ids, string orderByColumn, string orderType)
 private static List<RecordItem> CreateRecordItemsDesc()
        {
            var items = Builder<RecordItem>.CreateListOfSize(10).WhereAll().Have(x => x.Title = "sample title").WhereAll().Have(x => x.AuthorName = "Dhanushka").Build().ToList();
            var j = items.Count;
            for (int i = 1; i < items.Count + 1; i++)
            {
                EntityIdSetter.SetIdOf(items[i - 1], j);
                j--;
            }
            return items;
        }

Now lets use Rhino Mock to mock the Method Calls to the repository

public static IInventoryRepository CreateMockInventoryRepository()
        {
            var mocks = new MockRepository();
//specify the repository to mock
            var mockedRepository = mocks.StrictMock<IInventoryRepository>();


//specify what to return when a specific method is called in the mocked repository
            Expect.Call(mockedRepository.Stub(x => x.Get(Arg<List<int>>.Is.Anything)).Return(CreateRecordItems()));
            Expect.Call(mockedRepository.Stub(x => x.Get(Arg<List<int>>.Is.Anything, Arg<string>.Is.Anything, Arg<string>.Is.Equal("asc"))).Return(CreateRecordItems()));
            Expect.Call(mockedRepository.Stub(x =>x.Get(Arg<List<int>>.Is.Anything, Arg<string>.Is.Anything, Arg<string>.Is.Equal("desc"))).Return(CreateRecordItemsDesc()));

//mock the current data base context
            var mockedDbContext = mocks.StrictMock<IDbContext>();
            Expect.Call(mockedDbContext.CommitChanges);
            SetupResult.For(mockedRepository.DbContext).Return(mockedDbContext);

            mocks.Replay(mockedRepository);

            return mockedRepository;
        }

As you can see this method mocks the repository with specification for method calls return values and reveal the mocked repository to the outer world.

Now lets used this mocked repository to mock the service layer


public static IInventoryService   CreateMockClipboardService()
        {
            var serviceMock =new InventoryService(InventoryRepositoryMock.CreateMockInventoryRepository());
            return serviceMock;
        }

Here the dependency injection is used with Windsor Castle to inject the service with the mocked repository layer.

Now to write a sample test using NUnit all you have to do is
[TestFixture]
    public class ServiceTest
    {
        private IInventoryService  _service;

        [SetUp]
        public void SetUp()
        {
            _service = new InventoryService(InventoryRepositoryMock.CreateMockInventoryRepository());
        }

        [Test]
        public void GetWithoutSortTest()
        {
            var idList = new List<int> {1, 2, 3, 4};
            const int truncLength = 100;
            var itemsReturned = _service.Get(idList, truncLength);

            var expectedItemType = typeof (ServiceItem);
            const string expectedAuthor = "Dhanushka";
            const string expectedTitle = "sample title";

            Assert.That(itemsReturned.Count, Is.GreaterThan(0),"no items returned");
            Assert.That(itemsReturned[0], Is.TypeOf(expectedItemType),"incorrect return type");
            Assert.That(itemsReturned[0].Author,Is.EqualTo(expectedAuthor),"unexpected author returned");
            Assert.That(itemsReturned[0].Title,Is.EqualTo(expectedTitle),"unexpected title returned");

        }
   }

Now we have a simple unit test in our hand that uses a mocked service and repository layer

0 comments:

Post a Comment