如何单元测试数据库访问逻辑?

时间:2015-02-11 22:20:00

标签: c# sql-server entity-framework unit-testing ef-code-first

我有一个基于EF Code First使用MSSQL server的项目。在我的一个存储库中,我使用PredicateBuilder动态构建查询。要在每次代码中发生更改时手动测试所有可能的结果,都非常耗时。

出于这个原因,我想通过单元测试来实现自动化。我正考虑使用sql compact进行单元测试,MSSQL server进行生产。但是如何为sql compact服务器启用迁移?

这是dbContext类:

public partial class ApplicationDbContext :
        IdentityDbContext<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
    public ApplicationDbContext() : base("name=DefaultConnection") { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
        base.OnModelCreating(modelBuilder);
     }
}

存储库:

public class FilterRepository : IFilterRepository
{
    private ApplicationDbContext _dbContext;

    public FilterRepository(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
        DbInterception.Add(new CommandInterceptor());
    }

    public IEnumerable<Person> GetPersons(Filter filter)
    {
        try
        {
            var persons = PredicateBuilder.False<Person>();

            _dbContext.Configuration.AutoDetectChangesEnabled = false;

            var result = _dbContext.Persons
                            .AsNoTracking() 
                            .Where(persons)
                            .OrderBy(x => x.Name)
                            .Skip(filter.Skip)
                            .Take(10)
                            .ToList();

            _dbContext.Configuration.AutoDetectChangesEnabled = true;

            return result;
        }
        catch (Exception ex)
        {

        }
    }
}

1 个答案:

答案 0 :(得分:2)

好的,所以切换到另一个数据库进行测试是(imo)一个坏主意。

以下是一些适合您的术语,可以帮助您更好地组织测试。

单元测试用于测试您的业务功能,通常您只是为此模拟数据,因为您要测试域类中输入(数据)的变化,而不是它们来自何处。

集成测试用于测试业务域层与服务层的交互方式(您的数据层是服务层),我还会将查询的正确性视为集成测试,以便运行它们。 / p>

因此,在您的情况下,不要混淆事物,并可能添加因2个数据库的工作方式不同而导致的意外行为。如果您正在测试您的业务功能,请为此模拟您的数据。它的启动速度更快,您将进行测试,正是您想要测试的内容。

通过集成测试,您正在测试您与服务层的交互是否正确,在这种情况下,您的测试并未真正测试业务逻辑是否正常工作,应该在单元测试中进行测试;测试您的查询是否为其谓词返回正确的数据,以及要保留的任何数据是否正确保留。此外,任何正在进行的交易都按预期工作。场景的端到端测试也是一种有效的集成测试。

您绝对需要在与生产相同的数据库平台上执行此操作,不要期望SQL Compact和SQL Server的行为方式相同。

编辑...评论。

因此,模拟存储库调用的正常方式是使用依赖注入,您不必这样做,但它更简单,也是最佳实践。

我们的想法是,在您使用数据的域类中,首先从DI容器中获取存储库或查询类,该容器注入构造函数或从DI容器中提取

// in your domain class you would have something like...
    var repo = container.Get<IRepository>();
    var myList = repo.GetMyObjects(predcate);

因此,使用Moq,您现在可以简单地模拟该调用

//Where you do your container registration..
var repo = Mock<IRepository>
repo.Setup( o => o.GetMyObject(predecate)).Returns( (predecate) => <your dummy list>));
container.Register(repo.Object);
// Then later on your business domain object gets the dummy repo instead.

注意这是伪代码,每使用DI和Mocking框架会有所不同。