什么是将测试数据提供给模拟仓库的好方法

时间:2014-05-12 18:32:27

标签: entity-framework unit-testing

我有一个包含10-12个表的数据库(SQL Server,实体框架),大约有5000条记录。我想为使用这些表中的数据的复杂报告编写单元测试代码。有什么好办法呢?我真的不希望单元测试打到真正的数据库......

1 个答案:

答案 0 :(得分:0)

迟到回答,但它值得指出NuGet包Effort允许你从代码优先或数据库优先模型伪造内存中的整个DbContext。

我经常使用它&amp;喜欢它的易用性。您可以使用它来测试在尝试使用List<Entity>等具体假货进行单元测试时可能会遗漏的问题。 (例如,在处理上下文后尝试加载导航属性导致的问题)

缺点是它确实减慢了单元测试的速度 1 ,这可能是TDD或大量测试的一个问题,但我总是觉得它完全可以接受。

首次设置数据库的简单用例大纲如下:

  1. 为您的EF版本添加nuget包(包ID:Effort.EF6也许?)

  2. 将覆盖添加到&#34; MyEntities&#34;的构造函数中。 class,以使Effort能够传递自己的连接字符串:

  3. public partial class MyEntities
    {
        public MyEntities(DbConnection connection) : base(connection, true)
        {
        }
    }
    
    1. 您现在可以创建一个&#39; Persistent&#39; db store(持久性意味着它在上下文处理后仍然可用 - 在测试运行结束后它不会保存在任何地方!),代码如下:
    2. var context = new MyEntities(Effort.EntityConnectionFactory.CreatePersistent("name=MyEntities"))
      

      只需确保您的app.config中有可用于测试项目的数据库的连接字符串(仅用于创建模型)

      1. 设置测试上下文所需的任何模拟数据(我经常使用[ClassInitialize][TestInitialize]方法加载一些简单的数据,但它很容易做任何对你自己有意义的事情设置):
      2. [ClassInitialize]
        public static void Initialise()
        {
            using (var context = new MyEntities(Effort.EntityConnectionFactory.CreatePersistent("name=MyEntities")))
            {
                context.Employees.Add(new Employee { Name = "John Doe", Skills = null});
                context.Skills.Add(new Skill { Type = "C# Coding"});
        
                context.SaveChanges();
            }
        }
        
        1. 使用内存上下文运行您的单元测试:
        2. [TestMethod]
          public async Task CsSkillCanBeAssociatedWithEmployee()
          {
              //Arrange
              using (var context = new MyEntities(Effort.EntityConnectionFactory.CreatePersistent("name=MyEntities")))
              using (var sut = new SkillsMatrixService(context))
              {
          
              //Act
                  await sut.AddSkillToEmployeeAsync("Joe Bloggs","C# Coding");
              }
          
              //Assert
              using (var context = new MyEntities(Effort.EntityConnectionFactory.CreatePersistent("name=MyEntities")))
              {
                  var joesCSharpSkills = context
                      .Employees
                      .First(e => e.Name == "Joe Bloggs")
                      .Skills
                      .Where(s => s.Type == "C# Coding");
          
                  Assert.IsTrue(joesCSharpSkills.Any());
              }
          }
          

          我理解你可以从csv配置文件中为你的数据库加载初始设置,以便在你的项目中生存,但我总是只是在代码中设置虚拟数据。

          <子> 1。有趣的是,在我自己(相当有限的)体验中,大约1秒左右的时间通常会设置它并为一个小型模型加载一些虚拟数据,其中包含大约20个实体和大量导航属性 - 我的机器不是超快。当然,您的里程可能会根据您的型号和硬件设置的复杂程度而有所不同