【问题标题】:Unit Test .Net on Simple EF Function简单 EF 函数上的单元测试 .Net
【发布时间】:2013-02-28 09:31:34
【问题描述】:

我在 Asp.Net Web API 中有 3 层。使用 EF 实现的控制器层、服务层和存储库层。

我是单元测试的新手,并且有一个简单的函数,可以通过数据库中的 id 获取一个人,仅此而已。

基本上是服务层调用

Unit_Work.Person_Repository.GetPersonByID(id);

并且存储库会这样做:

return context.chapters.Where(p=>p.chapterID==id).SingleOrDefault();
  1. 我会在这上面写什么样的单元测试。
  2. 我应该使用数据库还是模拟实现。
  3. 我想过使用 Sql Server Compact 用模拟人填充它,然后尝试通过 ID 获取该人,这样是否正确。?

提前感谢所有回答的人。

【问题讨论】:

    标签: asp.net .net unit-testing


    【解决方案1】:

    如果您使用实体框架,则无法对数据访问层进行单元测试。

    Erik Alsmyr 提供的解决方案非常错误! 看看这里为什么 - What's the point of in memory IDbSet?

    当您在内存中使用数据库集时,您正在运行 Linq to Objects。当您使用 EF 的 DbContext 时,您的 Linq 将转换为 SQL。这是两个不同的东西!

    编写可以在内存数据库集中使用的代码非常容易(您的所有单元测试都会通过,您会很高兴)只是在您第一次尝试访问数据库时注意到运行时错误。

    让我们稍微修改一下这段代码。如果我们使用 FIRSTNAME、LASTNAME,我认为 FULLNAME 不应该有 setter。它应该由 FIRSTNAME 和 LASTNAME 计算得出。

    class User
    {
        public string FIRSTNAME { get; set; }
        public string LASTNAME { get; set; }
        public string FULLNAME
        {
            get { return string.Format("{0}, {1}", LASTNAME, FIRSTNAME }
        }
    
        User(string firstName, string lastName)
        {
            this.FIRSTNAME = firstName;
            this.LASTNAME = lastName;
        }
    }
    

    现在你可以像这样编写测试并且它会通过(当然是在你在控制器中实现之后)

    public IMyEntities GetRepoWithUsers(params User[] users)
    {
        var inMemoryUsers = new InMemoryDbSet<User>();
        var mockData = new Mock<IMyEntities>();
        mockData.Setup(m => m.Users).Returns(inMemoryUsers);
        return mockData.Object;      
    }
    [Test]
    public void GetUserByFullname()
    {          
        var ankaArne = new User("Arne", "Anka");
        var bjornBertil = new User("Bertil", "Björn");
        var repo = GetRepoWithUsers(ankaArne, bjornBertil);
    
        var usersController = new UsersController(repo);
    
        var found = usersController.GetUser("Anka, Arne");     
    
        Assert.NotNull(found);
        Assert.AreEqual("Anka", found.LASTNAME);
        Assert.AreEqual("Arne", found.FIRSTNAME);
    }
    

    但是,当您针对“真实”DbContext 和“真实”DbSet 运行它时,它会抛出异常,因为您无法对计算的属性进行 Linq 查询。仅在映射到数据库列的那些上。那么这个测试有什么意义呢?

    【讨论】:

      【解决方案2】:

      您可以将 xml/ .csv 文件用于数据。即,您需要从单元测试项目中的 xml 文件中获取 ID、章节详细信息。然后您必须将 id 作为参数传递,然后使用从 xml 文件中获取的数据检查返回值。如果你不明白,请告诉我。您可以通过添加新项目选项来创建单元测试项目。然后在 vs2010 上添加 xml 文件以获取要测试的数据。

      您的第三个问题也是正确的。 u cn 从数据库中填充数据并使用返回值检查数据

      【讨论】:

      • 这对你有用吗...如果对你有帮助,请作为答案。
      【解决方案3】:

      我建议模拟实体框架上下文并将其注入到您的存储库中。

      我们使用类似于 http://nuget.org/packages/FakeDbSet/ 的方式来完成此操作

      那么我们的单元测试是这样的:

      [TestFixture]
      class UsersControllerTester
      {
          private Mock<IMyEntities> mockData = null;
      
          [SetUp]
          public void Setup()
          {
              // Create fake data            
              var inMemoryUsers = new InMemoryDbSet<User>();
              inMemoryUsers.Add(new User { ID = 1, FIRSTNAME = "Arne", LASTNAME = "Anka", EMAIL = "arne.anka@email.com", FULLNAME = "Anka, Arne", USERNAME = "arne.anka" });
              inMemoryUsers.Add(new User { ID = 2, FIRSTNAME = "Bertil", LASTNAME = "Björn", EMAIL = "bertil.bjorn@email.com", FULLNAME = "Björn, Bertil", USERNAME = "bertil.bjorn" });
              inMemoryUsers.Add(new User { ID = 3, FIRSTNAME = "Carl", LASTNAME = "Cool", EMAIL = "carl.cool@email.com", FULLNAME = "Cool, Carl", USERNAME = "carl.cool" });
              inMemoryUsers.Add(new User { ID = 4, FIRSTNAME = "David", LASTNAME = "Dûsk", EMAIL = "david.dusk@email.com", FULLNAME = "Dûsk, David", USERNAME = "david.dusk" });
      
              // Create mock unit of work
              mockData = new Mock<IMyEntities>();
              mockData.Setup(m => m.Users).Returns(inMemoryUsers);      
          }
      
          [Test]
          public void GetUser()
          {           
              // Test
              var usersController = new UsersController(mockData.Object);
      
              // Invoke
              User user1 = usersController.GetUser("1");     
      
              // Assert
              Assert.NotNull(user1);
              Assert.AreEqual(1, user1.ID);
              Assert.AreEqual("Anka", user1.LASTNAME);
          }
      

      【讨论】:

        猜你喜欢
        • 2022-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-05
        • 2018-10-12
        • 1970-01-01
        相关资源
        最近更新 更多