【问题标题】:Why does this test fail under moq为什么这个测试在最小起订量下失败
【发布时间】:2014-06-09 19:58:17
【问题描述】:

使用最小起订量和通用存储库。我无法成功测试以下方法。

[TestMethod()]
    public void Employee_Service_Get_Users()
    {

        var mockRep = new Mock<IRepository<Employee>>(MockBehavior.Strict);

        IList<Employee> newEmpLst = new List<Employee>();
        Employee newEmp = new Employee();            

        mockRep.Setup(repos => repos.Find()   <------ What belongs here?

        var service = new EmployeeService(mockRep.Object);
        var createResult = service.GetAllActiveEmployees();

        Assert.AreEqual(newEmpLst, createResult);

    }

它正在调用这个方法:

public IList<Employee> GetAllActiveEmployees()
    {
        return _employeeRepository.Find()
               .Where(i=>(i.Status =="Active")).ToList();  <----It Bombs Here! ;)
    }

我的通用存储库有以下内容:

 public IQueryable<T> Find()
    {
        var table = this.LookupTableFor(typeof(T));
        return table.Cast<T>();
    }

我得到以下信息:

Moq.MockException: IRepository`1.Find() invocation failed with 
mock  behavior Strict. All invocations on the mock must have a corresponding 
setup.

【问题讨论】:

  • 你设置了一个repos.FindAll,而调用的依赖是_employeeRepository.Find()。您需要为Find() 添加Setup
  • 抱歉已编辑。我只是不确定我们如何为该函数调用 find() 。我不知道需要什么。

标签: unit-testing moq


【解决方案1】:

您还没有提供IRepository&lt;T&gt; Find() 的完整方法签名,但猜测它类似于IQueryable&lt;T&gt; Find()。因为我们想模拟它以返回少量的假数据,所以我们只是将它绑定到内存中的 List 并不重要。由于 SUT 执行过滤器 (Active),因此请确保您还在虚假数据中提供了不需要的数据,以确保 SUT 的过滤逻辑正常工作。

假设所有这些,您的设置将如下所示:

 var newEmpLst = new List<Employee>
 {
    new Employee()
    {
        Name = "Jones",
        Status = "Active"
    },
    new Employee()
    {
        Name = "Smith",
        Status = "Inactive"
    },
 };

mockRep.Setup(repos => repos.Find())
       .Returns(newEmpLst.AsQueryable());

您的 Act + Assert 将类似于:

var service = new EmployeeService(mockRep.Object);
var createResult = service.GetAllActiveEmployees();

Assert.AreEqual(1, createResult);
Assert.IsTrue(createResult.Any(x => x.Name == "Jones"));
Assert.IsFalse(createResult.Any(x => x.Name == "Smith"));

mockRep.Verify(repos => repos.Find(), Times.Exactly(1));

【讨论】:

  • 好的,这是有道理的。我在存储库中添加了 Find()。我没有 .AsQueryable 我使用的是最小起订量 4.2.1402.2112
  • AsQueryable 只是一个LINQ extension method。根据Find() 的实际签名,您也许可以完全不使用它。 More here
  • 什么是 SUT?正在测试的服务?
  • 它是 List&lt;T&gt;.AsQueryable() - 确保您的测试顶部有一个 using System.Linq;SUT = 被测系统 - 基本上是您实际测试的类/方法/无论是什么(而不是您正在模拟/伪造的依赖项):)
  • 为什么要使用 Times.Exactly(1) 而不是 Times.Once?表演有什么改进还是只是你采用的风格规则?
【解决方案2】:

您为FindAll 设置了一个期望,但随后调用了Find

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-10
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多