我试图使用Repository和Unit of Work模式进行单元测试MVC项目时遇到了麻烦

时间:2017-10-29 14:10:17

标签: c# asp.net-mvc unit-testing moq

所以我m can做对了,我尝试了大约5个小时,什么也没做。如果有人可以帮助我会很棒。 所以这是我的代码

MyContextFile:

    public class InventoryManagerContext : IdentityDbContext<ApplicationUser>, IInventoryManagerContext
{

    public InventoryManagerContext()
        : base("name=InventoryManager")
    {
    }

    public virtual IDbSet<Cloth> Clothes { get; set; }

    public static InventoryManagerContext Create()
    {
        return new InventoryManagerContext();
    }
}

我的数据文件:

public class InventoryManagerData: IInventoryManagerData
{
    private readonly DbContext context;
    private readonly Dictionary<Type, object> repositories = new Dictionary<Type, object>();

    public InventoryManagerData()
        : this(new InventoryManagerContext())
    {
    }

    public InventoryManagerData(DbContext context)
    {
        this.context = context;
    }

    private IRepository<T> GetRepository<T>() where T : class
    {
        if (!this.repositories.ContainsKey(typeof(T)))
        {
            var type = typeof(GenericRepository<T>);

            this.repositories.Add(typeof(T), Activator.CreateInstance(type, this.context));
        }

        return (IRepository<T>)this.repositories[typeof(T)];
    }

    public int SaveChanges()
    {
        return this.context.SaveChanges();
    }

    public void Dispose()
    {
        this.context.Dispose();
    }

    public IRepository<Cloth> Clothes
    {
        get { return this.GetRepository<Cloth>(); }
    }
}

和通用存储库失败:

    public class GenericRepository<T> : IRepository<T> where T : class
{
    //public GenericRepository()
    //    : this(new InventoryManagerContext())
    //{
    //}

    public GenericRepository(DbContext context)
    {
        if (context == null)
        {
            throw new ArgumentException("An instance of DbContext is required to use this repository.", "context");
        }

        this.Context = context;
        this.DbSet = this.Context.Set<T>();
    }

    protected IDbSet<T> DbSet { get; set; }

    protected DbContext Context { get; set; }

    public virtual IQueryable<T> All()
    {
        return this.DbSet.AsQueryable();
    }

    public virtual T GetById(int id)
    {
        return this.DbSet.Find(id);
    }

    public virtual void Add(T entity)
    {
        DbEntityEntry entry = this.Context.Entry(entity);
        if (entry.State != EntityState.Detached)
        {
            entry.State = EntityState.Added;
        }
        else
        {
            this.DbSet.Add(entity);
        }
    }

    public virtual void Update(T entity)
    {
        DbEntityEntry entry = this.Context.Entry(entity);
        if (entry.State == EntityState.Detached)
        {
            this.DbSet.Attach(entity);
        }

        entry.State = EntityState.Modified;
    }

    public virtual void Delete(T entity)
    {
        DbEntityEntry entry = this.Context.Entry(entity);
        if (entry.State != EntityState.Deleted)
        {
            entry.State = EntityState.Deleted;
        }
        else
        {
            this.DbSet.Attach(entity);
            this.DbSet.Remove(entity);
        }
    }

    public virtual void Delete(int id)
    {
        var entity = this.GetById(id);

        if (entity != null)
        {
            this.Delete(entity);
        }
    }

    public virtual void Detach(T entity)
    {
        DbEntityEntry entry = this.Context.Entry(entity);

        entry.State = EntityState.Detached;
    }
}

所以我m trying to make Fake Context and the pass it to the Data class, but without success. in the Test controller I尝试使用MOQ,例如:

 [TestMethod]
    public void Index_ShouldPass()
    {
        var mockContext = new Mock<IInventoryManagerContext>();

        foreach (var cloth in clothes)
        {
            mockContext.Object.Clothes.Add(cloth);
        }

        var mockMenuRepository = new Mock<IRepository<Cloth>>(mockContext.Object);
        var mockUnitOfWork = new Mock<InventoryManagerData>(mockContext.Object);

        mockUnitOfWork.Setup(e => e.Clothes).Returns(mockMenuRepository.Object);

        var menuItems = mockUnitOfWork.Object.Clothes.All();

        Assert.AreEqual(4, menuItems.Count());

    }

所以我有接口以及IInventoryManagerContext,IInventoryManagerData和IRepository以及所有添加,删除签名。

对于数据我有非常简单的Cloth对象列表。并试图在循环上下文中添加它们。但我最新的错误是:

测试错误: 消息:测试方法InventoryManager.Tests.Controllers.HomeControllerTests.Index_ShouldPass引发异常: System.NullReferenceException:未将对象引用设置为对象的实例。

已经绝望了......

0 个答案:

没有答案