Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework: Implement interfaces for unit test

today I wanted to start unit-testing a little asp.net MVC 3 Web (test) application to learn some new stuff.

But things went worse then I had expected ...

I've now read some threads about unit testing in relation with Entity framework and now I first want to implement interfaces for my entity framework related classes so that I can implement an in memory "database" for my unit tests.

My code base is from ASP.NET MVC tutorial. I've read MSDN but it doesn't help me in my cases.

I'd like to show you my code. I'm using a unit of work pattern with repositories:

Unit of work:

public class SqlUnitOfWork : IUnitOfWork, IDisposable
{
    private SqlContext context = new SqlContext();
    private IGenericRepository<Message> messageRepository;
    private IGenericRepository<Receipt> receiptRepository;
    private IGenericRepository<Useraccount> useraccountRepository;
    private bool disposed = false;

    public IGenericRepository<Message> MessageRepository
    {
        get
        {
            if (this.messageRepository == null)
            {
                this.messageRepository = new SqlGenericRepository<Message>(context);
            }
            return messageRepository;
        }
    }

    public IGenericRepository<Receipt> ReceiptRepository
    {
        get
        {
            if (this.receiptRepository == null)
            {
                this.receiptRepository = new SqlGenericRepository<Receipt>(context);
            }
            return receiptRepository;
        }
    }

    public IGenericRepository<Useraccount> UseraccountRepository
    {
        get
        {
            if (this.useraccountRepository == null)
            {
                this.useraccountRepository = new SqlGenericRepository<Useraccount>(context);
            }
            return useraccountRepository;
        }
    }

    public SqlUnitOfWork()
    {
    }

    ~SqlUnitOfWork()
    {
    }

    public virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }

        this.disposed = true;
    }

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

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

This one implements an interface I've created.

My generic repository for sql:

public class SqlGenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
    internal SqlContext context;
    internal DbSet<TEntity> dbSet;

    public SqlGenericRepository(SqlContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

    ~SqlGenericRepository()
    {
    }

    public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, 
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
    {
        IQueryable<TEntity> query = dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

    public virtual TEntity GetByID(object id)
    {
        return dbSet.Find(id);
    }

    public virtual void Insert(TEntity entity)
    {
        dbSet.Add(entity);
    }


    public virtual void Delete(object id)
    {
        TEntity entityToDelete = dbSet.Find(id);
        Delete(entityToDelete);
    }

    public virtual void Delete(TEntity entityToDelete)
    {
        if (context.Entry(entityToDelete).State == EntityState.Detached)
        {
            dbSet.Attach(entityToDelete);
        }
        dbSet.Remove(entityToDelete);
    }

    public virtual void Update(TEntity entityToUpdate)
    {
        dbSet.Attach(entityToUpdate);
        context.Entry(entityToUpdate).State = EntityState.Modified;
    }
}

It implements an interface I've programmed:

public interface IGenericRepository<TEntity> where TEntity : class
{
    IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");

    TEntity GetByID(object id);

    void Insert(TEntity entity);

    void Delete(object id);

    void Delete(TEntity entityToDelete);

    void Update(TEntity entityToUpdate);
}

I would now like to implement an "InMemoryGenericRepository" for my unit tests, then an "InMemoryUnitOfWork". How would those "InMemoryGenericRepository" look like?

I think I would use a generic List inside this repository where all data is stored:

IEnumerable<TEntity> List { get; set; }

But how can I adapt this method:

public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
    IQueryable<TEntity> query = dbSet;

    if (filter != null)
    {
        query = query.Where(filter);
    }

    foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
    {
        query = query.Include(includeProperty);
    }

    if (orderBy != null)
    {
        return orderBy(query).ToList();
    }
    else
    {
        return query.ToList();
    }
}

so it's working with my

IEnumerable<TEntity> List { get; set; }

I hope you made it until the end of my question.

like image 288
mosquito87 Avatar asked Jan 17 '26 17:01

mosquito87


1 Answers

If your classes are POCO then they're looking like this:

namespace Project.Model // auto-generated Foo.cs
{
    public partial class Foo // notice partiality
    {
    }
}

Then you write this:

namespace Project.Model // custom Foo.cs in another folder
{
    public partial class Foo : IEntity // notice interface
    {
    }
}
like image 61
abatishchev Avatar answered Jan 20 '26 22:01

abatishchev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!