如何在 ASP.NET MVC 单元测试中使用 Moq 模拟测试 class 本身的功能

How to mock the functionality of the test class itself using Moq in ASP.NET MVC unit test

我正在开发一个 ASP.NET MVC 项目。在我的项目中,我正在进行单元测试。我使用 Moq 进行单元测试。但是我在测试依赖于其另一个功能的模型 class 的方法时遇到问题。

这是我要测试的模型class的样本

public class ItemRepo:IItemRepo
{
    private DbContext context = new DbContext();

    public IEnumerable<Item> GetItems()
    {
        return context.items;
    }

    public string GenerateItemCode()
    {
       Item item = this.GetItems.OrderByDescending(x=>x.Id).FirstOrDefault();
       //do something
       return itemCode;
    }
}

我想测试 GenerateItemCode 方法

    [TestClass]
    public class ItemRepoTests
    {
        [TestMethod]
        public void GenerateItemCode_IncreaseDigit()
        {
            Item[] items = new Item[]{
                new Item{
                    ItemCode = "DN999934"
                }
            };
            ItemRepo itemRepo = new ItemRepo();
            //I want to mock GetItems method here
        }
    }

我在测试代码中评论了我想要模拟的内容。我如何模拟该方法?我如何对模拟依赖函数的方法进行单元测试?

用委托替换 GetItems:

 public class ItemRepo : IItemRepo
 {
     public Func<System.Collections.Generic.IEnumerable<Item>> Items = () => 
       {  // all your orignal code 
          return items;
       };  

      public string GenerateItemCode()
      {
         Item item = Items().OrderByDescending(x => x.Id).FirstOrDefault();
         //do something
         return itemCode;
      }
 }

在测试代码中替换您的委托:

 public class ItemRepoTests
 {
     [TestMethod]
     public void GenerateItemCode_IncreaseDigit()
     {
        Item[] items = new Item[]{
            new Item{
                ItemCode = "DN999934"
            }
        };
        ItemRepo itemRepo = new ItemRepo();
        itemRepo.Items = () => items;
        //I want to mock GetItems method here

         itemRepo.GenerateItemCode()
     }
  }

伪代码未测试,仅描述思路

您在评论中提到您正在从上下文 class 中获取项目,这就是您需要 Mocking 的 class。

周围有很多文章解释了如何模拟 DbContext,在 google 搜索中获得最高结果 How to mock DbContext and DbSet with Moq for unit testing?

[TestClass]
public class ItemRepoTests
{
    [TestMethod]
    public void GenerateItemCode_IncreaseDigit()
    {
       Item[] items = new Item[]{
               new Item{
                          ItemCode = "DN999934"
                       }
        };

       var mockContext = new Mock<YourContext>();
       // Code to inject items into mock context

       // You may have to implement the context injection into your ItemRepo 
       // class if you do not already have it

       ItemRepo itemRepo = new ItemRepo(mockContext.Object);

       var result = itemRepo.GenerateItemCode();

      // Code to check result is correct
   }
}

基本上,您在单元测试中创建了一个模拟 DbContext,并传入了一个虚假列表或类似的项目数据。然后你将这个模拟注入你正在测试的 class,运行 测试,如果你的代码一切正常,正确的结果将在另一端吐出