Earlier I wrote an article about how to mock the LINQ DataContext. I promised to write an article about how to do the same method with Entity Framework. It’s quite similar, but the only difference is creating an IDbContext interface and using DbSet<T>.

You can get the code from GitHub

The method

The main point is to create a Unit Of Work pattern that handles the context and keeps track of our repositories. The repository is then accessable through a Generic Repository pattern that specifies the same functions for all model classes, mocked or real.

Next we create a service layer which handles all business logic. It only contains IUnitOfWork interface, so with IoC / dependency injection we can inject either real or mocked UnitOfWork. The service layer doesn’t care what kind of data it is getting. It just talks to Unit Of Work which then delivers the data. This is so we can test our logic (service layer) in isolation. When you have many services that use the same Unit Of Work instance, you don’t have to worry about DataReader conflicts, because the Unit Of Work only makes a DataContext instance in the constructor, when an instance of UnitOfWork is created. So when dealing with many services, you only have one instance of the context. Unit Of Work handles that for us.

Student example

In this example I will use a model class named Student. Our Student model would look something like this:

public class Student
{
    public int id { get; set; }
    public string name { get; set; }
}

We start off by creating an interface for DbContext, called IDbContext, which our DataContext and MockDataContext will implement.

Here is theIDbContext interface:

public interface IDbContext
{
    DbSet<T> Set<T>() where T : class;
    DbEntityEntry<T> Entry<T>(T entity) where T : class;
    int SaveChanges();
    void Dispose();
}

Next I created an StudentDBContext class, which will inherit DbContext base class and implement IDbContext.

Here is the StudentDBContext class:

public partial class StudentDBContext : DbContext, IDbContext
{
    static StudentDBContext()
    {
        Database.SetInitializer<StudentDBContext>(null);
    }

    public StudentDBContext()
        : base("Name=StudentDBContext")
    {
    }

    public DbSet<Student> Students { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new StudentMap());
    }
}

Also the mapping class for the Student.

Here is the StudentMap class:

public class StudentMap : EntityTypeConfiguration<Student>
{
    public StudentMap()
    {
        // Primary Key
        this.HasKey(t => t.id);

        // Properties
        this.Property(t => t.name)
            .HasMaxLength(100);

        // Table & Column Mappings
        this.ToTable("Students");
        this.Property(t => t.id).HasColumnName("id");
        this.Property(t => t.name).HasColumnName("name");
    }
}

Generic Repository

I used a Generic Repository pattern to access my model classes. This is so I have generic actions for each model class (add/delete/update/getall, etc).

Here is my IRepository interface:

public interface IRepository<T> where T : class
{
    IQueryable<T> GetAll();
    void Add(T entity);
    void Delete(T entity);
    void DeleteAll(IEnumerable<T> entity);
    void Update(T entity);
    bool Any();
}

Next I created the Repository class that implements the interface. This class will work with AppDataContext, which is our EF DataContext. Later on we will also create a MockRepository that will handle our mocked data, but here is my Repository class:

public class Repository<T> : IRepository<T> where T : class
{
    private readonly IDbContext _context;
    private readonly IDbSet<T> _dbset;

    public Repository(IDbContext context)
    {
        _context = context;
        _dbset = context.Set<T>();
    }

    public virtual IQueryable<T> GetAll()
    {
        return _dbset;
    }

    public virtual void Add(T entity)
    {
        _dbset.Add(entity);
    }

    public virtual void Delete(T entity)
    {
        var entry = _context.Entry(entity);
        entry.State = EntityState.Deleted;
        _dbset.Remove(entity);
    }

    public virtual void DeleteAll(IEnumerable<T> entity)
    {
        foreach (var ent in entity)
        {
            var entry = _context.Entry(ent);
            entry.State = EntityState.Deleted;
            _dbset.Remove(ent);
        }
    }

    public virtual void Update(T entity)
    {
        var entry = _context.Entry(entity);
        _dbset.Attach(entity);
        entry.State = EntityState.Modified;
    }

    public virtual bool Any()
    {
        return _dbset.Any();
    }
}

Unit Of Work

Next step is to create the Unit Of Work. We start off by creating an interface that both our EF UnitOfWork and our MockUnitOfWork will implement.

Here is the IUnitOfWork interface:

public interface IUnitOfWork : IDisposable
{
    IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
    void Save();
}

Next we create a class that implements our interface. Again, this is the class that works with EF AppDataContext, not our mocked one.

Here is the UnitOfWork class:

public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new()
{
    private readonly IDbContext _ctx;
    private Dictionary<Type, object> _repositories;
    private bool _disposed;

    public UnitOfWork()
    {
        _ctx = new TContext();
        _repositories = new Dictionary<Type, object>();
        _disposed = false;
    }

    public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
    {
        // Checks if the Dictionary Key contains the Model class
        if (_repositories.Keys.Contains(typeof(TEntity)))
        {
            // Return the repository for that Model class
            return _repositories[typeof(TEntity)] as IRepository<TEntity>;
        }

        // If the repository for that Model class doesn't exist, create it
        var repository = new Repository<TEntity>(_ctx);

        // Add it to the dictionary
        _repositories.Add(typeof(TEntity), repository);

        return repository;
    }

    public void Save()
    {
        _ctx.SaveChanges();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this._disposed)
        {
            if (disposing)
            {
                _ctx.Dispose();
            }

            this._disposed = true;
        }
    }
}

Service layer

All of our business logic will be created in a service layer, because the controllers should not contain any logic. This is so all our logic can be in one place and that the same logic can be unit tested with mocked data.

So here is my StudentService class:

public class StudentService
{
    private IUnitOfWork _uow;

    private IRepository<Student> _Student;

    public StudentService(IUnitOfWork uow)
    {
        _uow = uow;

        _Student = _uow.GetRepository<Student>();
    }

    public IEnumerable<Student> GetAllStudents()
    {
        return _Student.GetAll();
    }

    public Student GetStudentByID(int id)
    {
        try
        {
            return _Student.GetAll().Where(s => s.id == id).SingleOrDefault();
        }
        catch (Exception ex)
        {
            throw new Exception("Failure getting student", ex);
        }
    }

    public void DeleteStudentByID(int id)
    {
        try
        {
            Student model = _Student.GetAll().Where(s => s.id == id).SingleOrDefault();
            _Student.Delete(model);
            _uow.Save();
        }
        catch (Exception ex)
        {
            throw new Exception("Failure deleting student", ex);
        }
    }
}

Mocking

Next we create a seperate implementation of our Repository and UnitOfWork classes, to work with mocked data. It’s a good practice to keep this in a seperate test project, in a namespace/folder called Mock or something like that.

Here is my MockRepository class:

public class MockRepository<T> : IRepository<T> where T : class
{
    public List<T> _context;

    public MockRepository(List<T> ctx)
    {
        _context = ctx;
    }

    public virtual IQueryable<T> GetAll()
    {
        return _context.AsQueryable();
    }

    public virtual void Add(T entity)
    {
        _context.Add(entity);
    }

    public virtual void Delete(T entity)
    {
        _context.Remove(entity);
    }

    public virtual void DeleteAll(IEnumerable<T> entity)
    {
        _context.RemoveAll(s => s == entity);
    }

    public virtual void Update(T entity)
    {
        var entry = _context.Where(s => s == entity).SingleOrDefault();
        entry = entity;
    }

    public virtual bool Any()
    {
        return _context.Any();
    }
}

Here is my MockUnitOfWork class:

public class MockUnitOfWork<T> : IUnitOfWork where T : class, new()
{
    private T _ctx;
    private Dictionary<Type, object> _repositories;

    public MockUnitOfWork()
    {
        _ctx = new T();
        _repositories = new Dictionary<Type, object>();
    }

    public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
    {
        if (_repositories.Keys.Contains(typeof(TEntity)))
        {
            return _repositories[typeof(TEntity)] as IRepository<TEntity>;
        }

        var entityName = typeof(TEntity).Name;
        var prop = _ctx.GetType().GetProperty(entityName);
        MockRepository<TEntity> repository = null;
        if (prop != null)
        {
            var entityValue = prop.GetValue(_ctx, null);
            repository = new MockRepository<TEntity>(entityValue as List<TEntity>);
        }
        else
        {
            repository = new MockRepository<TEntity>(new List<TEntity>());
        }
        _repositories.Add(typeof(TEntity), repository);
        return repository;
    }

    public void SetRepositoryData<TEntity>(List<TEntity> data) where TEntity : class
    {
        IRepository<TEntity> repo = GetRepository<TEntity>();

        var mockRepo = repo as MockRepository<TEntity>;
        if (mockRepo != null)
        {
            mockRepo._context = data;
        }
    }

    public void Save()
    {
    }

    public void Dispose()
    {
    }
}

Unit Test

Next we create our unit tests against our service layer. The service layer doesn’t care where it gets the data from. All it knows it talks to Unit Of Work that provides the data. This is so the logic can be unit tested in isolation. But first we need to implement our mocked AppDataContext with our fake data.

Here is the MockDataContext class:

public class MockDataContext
{
    public List<Student> Student
    {
        get
        {
            return new List<Student>
        {
            new Student
            {
                id = 1,
                name = "John Doe",
            },
            new Student
            {
                id = 2,
                name = "Victor Sagev",
            },
            new Student
            {
                id = 3,
                name = "Wayne Johnson",
            }
        };
        }
    }
}

I created an example StudentServiceTest that tests all functions in the StudentService class. For this I use VisualStudio UnitTest library (Microsoft.VisualStudio.TestTools.UnitTesting).

Here is the StudentServiceTest class:

[TestClass]
public class StudentServiceTest
{
    IUnitOfWork _uow;
    StudentService _studentService;

    [TestInitialize]
    public void SetUp()
    {
        _uow = new MockUnitOfWork<MockDataContext>();
        _studentService = new StudentService(_uow);
    }

    [TestCleanup]
    public void TearDown()
    {
        // Clean resources
    }

    [TestMethod]
    public void TestGetStudentJohnDoe()
    {
        var student = _studentService.GetStudentByID(1);
        Assert.AreEqual(student.name, "John Doe");
    }

    [TestMethod]
    public void TestDeleteStudentJohnDoe()
    {
        try
        {
            _studentService.DeleteStudentByID(1);
        }
        catch(Exception ex)
        {
            Assert.Fail("Expected no exception, but got: " + ex.Message);
        }
    }
}

So here we go. This is my method of creating a mocked testable service layer with mocked/real DataContext, using Unit Of Work and Generic Repository pattern.