使用ms单元测试框架的单元测试实体框架

时间:2016-07-15 18:36:17

标签: entity-framework unit-testing

我正在使用ms unit test对我正在使用Entity Framework的项目进行单元测试。我可以使用以下示例来模拟它  Msdn 但我有一个场景,我需要在实体框架中使用事务 以下列方式

Var tran = testdbcontext.Database.BeginTransaction()

并且测试失败,因为testdbcontext的数据库为null。

我想知道我们是否可以以某种方式嘲笑它以使其正常工作

1 个答案:

答案 0 :(得分:1)

使用链接的MSDN文章作为参考,您会注意到它们已经抽象了DbContext。使用相同的思路,您还应该抽象出事务的创建。

首先创建事务对象的预期功能的抽象。

/// <summary>
/// Wraps access to the transaction object on the underlying store connection
/// </summary>
public interface IDbContextTransaction : IDisposable {
    /// <summary>
    ///  Commits the underlying store transaction
    /// </summary>
    void Commit();
    /// <summary>
    /// Rolls back the underlying store transaction
    /// </summary>
    void Rollback();
}

这反映了您希望从数据库事务中获得的功能。

对于生产,您可以使用这样的实现来包装您想要使用的实际对象。

public class DbContextTransactionWrapper : IDbContextTransaction {
    private DbContextTransaction dbContextTransaction;

    public DbContextTransactionWrapper(DbContextTransaction dbContextTransaction) {
        this.dbContextTransaction = dbContextTransaction;
    }

    public void Commit() {
        dbContextTransaction.Commit();
    }

    public void Rollback() {
        dbContextTransaction.Rollback();
    }

    public void Dispose() {
        if(dbContextTransaction != null) {
            dbContextTransaction.Dispose();
            dbContextTransaction = null;
        }
    }
}

DbContext抽象将包括创建事务的能力......

public interface IStoreAppContext : IDisposable {
    DbSet<Product> Products { get; }
    int SaveChanges();
    void MarkAsModified(Product item);
    IDbContextTransaction BeginTransaction();  
}

并且实现将使用包装器

public class StoreAppContext : DbContext, IStoreAppContext
{
    public StoreAppContext() : base("name=StoreAppContext")
    {
    }

    public DbSet<Product> Products { get; set; }

    public void MarkAsModified(Product item)
    {
        Entry(item).State = EntityState.Modified;
    }

    public IDbContextTransaction BeginTransaction() {
        return new DbContextTransactionWrapper(Database.BeginTransaction());
    }
}

这样,在您的单元测试中,您可以通过模拟框架或虚假实现来模拟事务的创建,您将直接在抽象的DbContext上调用它。

假设testdbcontext的类型为IStoreAppContext,那么您的通话就像......

IDbContextTransaction tran = testdbcontext.BeginTransaction();

这将使您能够访问界面上定义的tran.Commit()tran.Rollback(),并且可以轻松进行测试。