【问题标题】:Integration Testing Entity Framework code first with in-memory database首先使用内存数据库集成测试实体框架代码
【发布时间】:2011-05-06 13:27:52
【问题描述】:

我想针对内存数据库运行我的 EF4.1 存储库的实际集成测试,例如 ayende's nhibernate version

我有一个代码优先模型,针对旧数据库(旧表和列名需要使用代码配置映射到我的实体)。

我希望能够使用 Sqlite(或其他)来:

  1. 从我的模型生成内存数据库
  2. 使用这个内存数据库为我的模型创建一个 DBContext
  3. 我已经设置了 IDBContextFactory 的 IoC/DI,它使用我的(通用)存储库(也使用 GenericRepository 模式)构建

网上有一些信息表明它应该是可能的,但对于代码优先的方法来说并不多。有人知道这是否可能吗?

我的测试库的一些 sn-ps,见 // THROWS ERROR 标记运行时错误:

public class MyDbContextFactory : IDbContextFactory
  {
    private static object context;
    public object CurrentContext
    {
      get {
        if(context == null)
        {
          // ?? DOESN'T WORK AS THERE'S NO META DATA
          var connBuilder = new EntityConnectionStringBuilder();
          connBuilder.Provider = "System.Data.SQLite";
          connBuilder.Metadata = 
           @"res://*/TestEfDb.csdl|res://*/TestEfDb.ssdl|res://*/TestEfDb.msl";
          connBuilder.ProviderConnectionString = 
           ConfigurationManager.ConnectionStrings["DataContext"].Name;

          var entConnection = new EntityConnection(connBuilder.ConnectionString);

          // THROWS ERROR: sqlite Format of the initialization string does not
          // conform to specification starting at index 0
          // for connection string "Data Source=:memory:;Version=3;New=True;"

          //var entConnection = new EntityConnection
          // (ConfigurationManager.ConnectionStrings["DataContext"].Name);
          context = new MyDbContext(entConnection);
        }
        return context;
      }
    }
  }

...

 [Test]
    public void test_me()
    {
        var auditRespository = new AuditRepository(new MyDbContextFactory());
        auditRespository.GetAll<Audit>();
    }

【问题讨论】:

  • 您多次首先提到代码,但同时您正在构建实体连接字符串,引用来自 EDMX 文件的资源文件(设计器),那么您使用的是哪种方法?
  • quote: "?? DOESNT WORK AS THERES NO META DATA" 它的代码优先

标签: sqlite entity-framework-4.1 ef-code-first


【解决方案1】:

使用 SQL Compact 4.0(通过 Web 平台安装程序下载 SqlCE 和工具)- EF Code 首先直接支持该功能。唯一的区别是您的应用程序将使用连接字符串到大型 SQL Server:

<add name="MyDbContext" 
     provider="System.Data.SqlClient" 
     connectionString=
       "Data Source=...;InitialCatalog=...;Integrated Security=SSPI" />

您的测试将使用 SQL Compact 的连接字符串:

<add name="MyDbContext" 
     provider="System.Data.SqlServerCe.4.0" 
     connectionString="Data Source=Database.sdf" />

【讨论】:

  • 太棒了。工作一种享受。谢谢!
  • 我仍然不考虑这个单元测试,因为您需要在每次测试后进行某种清理以保持数据库处于一致状态。
  • @Steven:这不是单元测试。它是集成测试,根据我的经验,这是使用 IQueryable 和 EF 真正测试代码的唯一可行方法。我稍后会阅读您的链接文章。
  • @Ladislay:使用任何 O/RM 工具时,我们都需要集成测试。至少我们需要确保映射层定义正确,并且我们需要为此进行集成测试。我认为我们同意这一点。但是对于测试业务逻辑来说,进行单元测试更有价值,因为它们运行得更快并且更容易维护。但同样,我们不应该只赌单元测试。
  • @Steven:我知道这个理论并且我使用了它,但它不适用于在业务逻辑中定义查询。一旦我们运行了单元测试,我们就使用 linq-to-objects 而不是 linq-to-entities 并且测试是绿色的,但是当我们使用 EF 提供程序运行相同的查询时,很多时候代码不起作用。 Linq-to-entities 只是 linq 功能的子集,所以我更喜欢直接使用真正的数据库提供程序测试查询。
【解决方案2】:

看看这篇文章:Faking your LINQ provider。它描述了如何将实体框架隐藏在抽象之后,以便您可以轻松地对应用程序进行单元测试,同时仍然允许在应用程序代码中对其使用 LINQ(通过 IQueryable)查询。

请注意,这并不能完全消除编写集成测试的需要,因为您仍需要测试数据库映射层并可能测试所选的 LINQ 提供程序是否能够执行 LINQ 查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多