2015-02-11 63 views
0

我有一个项目基于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) 
     { 

     } 
    } 
} 
+0

请参阅http://stackoverflow.com/questions/9907905/entity-framework-code-first-how-to-seed-a-database-for-unit-testing。简而言之 - 创建一个初始化程序,它将删除并重新创建紧凑型数据库,然后对其进行播种。在单元测试开始时初始化上下文,并且每次运行测试时都会重新创建它。但是,如果你想打一个数据库,这比单元测试更像是一个集成测试。 – 2015-02-11 22:52:46

回答

2

OK,所以切换到不同的数据库进行测试(IMO)是一个坏主意。

这里有一些术语可以帮助你更好地组织你的测试。

单元测试用于测试您的业务功能,通常您只需为此模拟您的数据,因为您想测试您的域类中的输入(数据)发生了什么,而不是它们来自哪里。

集成测试旨在测试您的业务域层如何与您的服务层进行交互(您的数据层是服务层),我还将测试查询的正确性作为集成测试来运行它们。

因此,就您的情况而言,不要混淆事物并且可能会添加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); 

因此,与起订量的可现在根本嘲笑这一呼吁

//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略有不同,并嘲讽使用框架。

+0

如果我嘲笑数据,如何将模拟数据传递给我的存储库?在一分钟或1分钟内查看我的更新答案以获取存储库代码。 – Quoter 2015-02-11 22:59:46

+0

您的模拟存储库将返回您为给定测试设置的数据。请参阅https://github.com/Moq/moq4/wiki/Quickstart。也就是说,您可以配置模拟,以便对“GetPersons”的调用将针对您的测试数据进行操作。 – 2015-02-11 23:10:23

+0

@Tim Jarvis,我在创建内存中的数据库时遇到了困难,并且遇到了以下博客文章:https://msdn.microsoft.com/en-US/data/dn314431#doubles。他们为他们的dbcontext创建了一个接口来填充内存数据库。这是一个很好的帖子,用它作为参考? – Quoter 2015-02-12 18:30:06

相关问题