1

我有一个数据库存储库类:

public class DatabaseRepository : IRepository
    {
        private readonly Database _database;

        public DatabaseRepository(Database database)
        {
            _database = database;
        }

        ...

        public void Delete<TObject>(TObject entity) where TObject : BaseEntity
        {
            var dbSet = DbSet<TObject>();
            dbSet.Remove(entity);
            Save();
        }

        ...

        private void Save()
        {
            try
            {
                 _database.SaveChanges();
            }
            catch(DbEntityValidationException dbEx)
            {
                // do some action
            }
        }    
    }

我需要测试方法catchprivate void Save(),所以我需要类似...

[TestMethod]
public void SaveShouldDoSomethingIfDabaBaseConnectFalls()
{
    Mock<Database> mockDb = new Mock<Database>();
    mockDb.Setup(db => db.SaveChange()).Throws(new DbEntityValidationException());

    IRepository repository = new DatabaseRepository(mockDb.Object);

    ...
}

所以我的问题是如何模拟实体框架数据库?Mock<Database> mockDb = new Mock<Database>();- 怎么写正确???为了嘲笑我使用Moq.

4

1 回答 1

4
  1. 使用一组典型属性为您定义IDatabase接口DbContextIIDbSet<T>
  2. 实施FakeDbSet<T>: IDbSet<T>
  3. 更新Repository以使用IDatabase而不是Database

之后,您可以构造IDatabase.

http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/

这样做时请记住,针对假数据库集实施的单元测试并不能保证您的代码可以针对真实数据库运行。

LINQ-to-Entities (real DbSet) 不支持 LINQ-to-Objects ( FakeDbSet) 支持的许多功能。因此,当您使用数据库时,您的代码可能会在执行时失败。

此限制不会使针对伪造 DbSet 实施的单元测试毫无用处。测试仍然可以测试在您的存储库中实现的业务规则。但是您需要针对真实数据库 LINQ-to-Entities db 提供程序运行每个更新的 linq 语句(手动或来自集成测试),以确保该提供程序支持它。

这里有关于这个“圣战”主题的更多信息 - Fake DbContext of Entity Framework 4.1 to Test

于 2012-07-13T03:01:37.050 回答