简体   繁体   中英

Unit test of generic repository using NUnit and NSubstitute

How can I perform Units tests, using NUNit and NSubstitute, I want to test inserting a fake "GamaItem" object, and validate that it works, and if the SaveChanges has been triggered.

Im new in unit test, and Im not sure of how can I fake the dbContext object.

Thanks in advance.

Unit of Work:

public class UnitOfWork: IUnitOfWork, IDisposable
{
    private SRColorContext context = new SRColorContext();
    private GenericEntityRepository<HairColorType> hairColorTypeRepository;
    private GenericEntityRepository<GamaItem> gamaItemRepository;

    public UnitOfWork()
    {
        if (context == null)
        {
            context = new SRColorContext();
        }
    }

    public UnitOfWork(SRColorContext context)
    {
        this.context = context;
    }


    public GenericEntityRepository<HairColorType> HairColorTypeRepository
    {
        get
        {
            if (this.hairColorTypeRepository == null)
            {
                this.hairColorTypeRepository = new GenericEntityRepository<HairColorType>(context);
            }
            return hairColorTypeRepository;
        }
    }

    public GenericEntityRepository<GamaItem> GamaItemRepository
    { 
        get
        {
            if (this.gamaItemRepository == null)
            {
                this.gamaItemRepository = new GenericEntityRepository<GamaItem>(context);
            }
            return gamaItemRepository;
        }
    }

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

    private bool disposed = false;


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


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

Generic Repository:

public class GenericEntityRepository<TEntity> where TEntity : class
{
    internal SRColorContext context;
    internal DbSet<TEntity> dbSet;

    public GenericEntityRepository(SRColorContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

    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.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;
    }
}

I think you should fake the context object to avoid calling a DB and not the entity (unless you cannot simple create one)

In case you want to write unit tests for UnitOfWork class and you're using NSubtitute (or any other .NET OSS Mocking framework) you have to use dependency injection and replace the context instance with a fake instance.

You might also need to wrap the context class - if it's sealed or the methods used are not virtual.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM