lbrt.Net

Pinoy Software Engineer

Repository Pattern – Mocking with Entity Framework 4.0: A Generic Approach

Today I will present a mocking approach I have applied for Entity Framework 4.0. Unlike other Repository Pattern, The approach I’ve created is more generic in terms that you wouldn’t need to create specific concrete class that would implement IRepository Interface. For more details about Repository and Unit of work pattern please refer to this.

Why use Repository Pattern?
The reason is simple, It gives the ability to mock an ObjectContext, where in our example, is entity framework 4.0

First off, we need to define the IRepository interface. The example below will allow user the basic CRUDE operations interface.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Model.Model.Contracts
{
    public interface IRepository
    {
        IQueryable<TEntity> GetEntitySet<TEntity>() where TEntity : class;
        int SaveChanges();
        int SaveChangesPersist();
        void AcceptAllChanges();
        void AddObject<TEntity>(TEntity entity) where TEntity : class;
        object GetObjectByKey(string entityKey);
    }
}

Next is we need to construct the base repository to be used which would implement the IRepository pattern. This base repository class will handle all Repository Concrete Implementation instead of the usual creation of Repository concrete classes for each Data Entity, therefor would help create a more leaner approach on repository pattern.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using Model.Model.Contracts;
using System.Xml.Serialization;
using System.Data;
using System.IO;

namespace Model.Model.Shared
{
    public class RepositoryBase : IRepository
    {
        ObjectContext _dtx;
        public RepositoryBase(ObjectContext dtx)
        {
            _dtx = dtx;
            _dtx.CommandTimeout = 1800;
        }

        public IQueryable<TEntity> GetEntitySet<TEntity>() where TEntity : class
        {
            return _dtx.CreateObjectSet<TEntity>();
        }

        public int SaveChanges()
        {
            return _dtx.SaveChanges();
        }

        public int SaveChangesPersist()
        {
            return _dtx.SaveChanges(false);
        }

        public void AcceptAllChanges()
        {
            _dtx.AcceptAllChanges();
        }

        public void AddObject<TEntity>(TEntity entity) where TEntity : class
        {
            var objectSet = _dtx.CreateObjectSet<TEntity>();

            if (objectSet != null)
            {
                objectSet.AddObject(entity);
            }
            else
            {
                throw new Exception("EntitySet is not found.");
            }
        }

        public object GetObjectByKey(string entityKeyStr)
        {
            var serializer = new XmlSerializer(typeof(EntityKey));
            var reader = new StringReader(entityKeyStr);
            var entityKey = serializer.Deserialize(reader) as EntityKey;

            if (entityKey != null)
            {
                return _dtx.GetObjectByKey(entityKey);
            }

            return default(object);
        }
    }
}

Now to use this is simple, I’ve created a sample class below that would retrieve data from a AdventureWorks created EDMX.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Model.Model.Contracts;
using Model.Model.Shared;
using Model.Utilities.Extensions;

namespace Model.Model.AdventureWorks
{
    public class ProductModel : IProductModel
    {
        IRepository _dtx;
        public ProductModel()
        {
            _dtx = new RepositoryBase(new AdventureWorksEntities());
        }
        public ProductModel(IRepository dtx)
        {
            _dtx = dtx;
        }

        public IEnumerable<Product> GetProductList(int pageNumber, int pageSize, out int totalRecords)
        {
            var products = from p in _dtx.GetEntitySet<Product>()
                           select p;

            totalRecords = products.Count();
            products = products.OrderBy(x => x.ProductID).Page(pageNumber, pageSize);

            return products.ToList();
        }
    }

   public interface IProductModel
   {
        IEnumerable<Product> GetProductList(int pageNumber, int pageSize, out int totalRecords);
   }
}

Now we can freely create Mock Repositories for our testing. Following example uses a mocking framework called Moq. This code demontrates how to create a Mock object from the IRepository interface.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SampleMVCApplication.Controllers;
using SampleMVCApplication.Tests.Helpers;
using Model.Model.Contracts;
using System.Linq;
using Model;
using System.Collections.Generic;

namespace SampleMVCApplication.Tests.Controllers
{
    [TestClass]
    public class AdventureWorksControllerTest
    {
        static Mock<IRepository> _mockRepository = new Mock<IRepository>();
        static Mock<IProductModel> _mockModel = new Mock<IProductModel>();

        [TestInitialize]
        public void InitializeTest()
        {
            _mockModel.SetupAllProperties();
            _mockRepository.SetupAllProperties();
        }

        [TestMethod]
        public void InvokeGridData()
        {
            var totalRecords = 0;
            var pageSize = 5;
            var pageNum = 1;

            var controller = new AdventureWorksController(_mockModel.Object);
            _mockModel.Setup(x => x.GetProductList(pageNum, pageSize, out totalRecords)).Returns(FakeProducts());
            var result = controller.GridData(It.IsAny<string>(), It.IsAny<string>(), pageNum, pageSize);

            Assert.IsNotNull(result);
        }

        private static IQueryable<Product> FakeProducts()
        {
            var productList = new List<Product>();
            productList.Add(new Product() { ProductID = 1, Name = "testName", ListPrice = 10, ProductNumber = "Test101" });
            return productList.AsQueryable();
        }
    }
}

Conclusion?
The example above illustrate’s how easy it is to create a Mockable Entity Framework for C#. Thanks for reading. Hope it helps!

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

%d bloggers like this: