使用 Moq 安排单元测试

Arranging Unit Test using Moq

我创建了一个名为 ListOfPeople 的方法,并尝试为其编写 单元测试 。目前,我在设置 单元测试 Arrange 部分时遇到问题。我现在不能 运行 因为我的 PeopleIdPersonGroupJobId 状态 Cannot resolve symbol

Question: How can I test this method successfully?

我的方法:

public IEnumerable<Person> ListOfPeople(int personId, int? jobId)
        {
            var people = _unitOfWork.GetRepository<DB.Person>().GetAll()
              .Where(p => p.PeopleGroups.Any(m => m.PeopleId == personId 
                              && m.PersonGroupdJobId == jobId));

            if (!people.Any())
                return new List<Person>();

            var personData = people.Select(p => new Person
            {
                Id = p.PersonId,
                Name = p.PersonName,
                WorkTypeId = p.WorkTypeId,
                PrimaryLanguage = p.PrimaryLanguage,
                PeopleGroups = p.PeopleGroups.ToList()
                  .Select(pp => new PeopleGroup
                  {
                      Id = pp.ProjectPartyId,
                      PeopleId = pp.PeopleId,
                      JobId = pp.PersonGroupJobId ?? 0,
                      AddressId = pp.AddressId
                  })
            }).ToList();

            return personData;
        }

单元测试:

[TestMethod]
    public void ListOfPeople_peopleExist_returnsList()
    {
        // Arrange
        var people = new List<DB.Person>
        {    
            PeopleId = It.IsAny<int>(),
            PersonGroupdJobId = It.IsAny<int>()
        }; 

        _uowMock
            .Setup(mock => mock.GetRepository<DB.Person>().GetAll())
            .Returns(people.AsQueryable());

        // Act
        var result = _repository.ListOfPeople(It.IsAny<int>(), It.IsAny<int>());

        // Assert
        Assert.IsNotNull(result);
        Assert.AreEqual(2, result.Count());

        _unitOfWork.Verify(mock => mock.Commit(), Times.Never());
        _unitOfWork.Verify(mock => mock.GetRepository<DB.Person>().GetAll(), Times.Once());
    }

您没有正确初始化列表。您需要:

var people = new List<DB.Person>
{
    new DB.Person
    {    
        PeopleId = It.IsAny<int>(),
        PersonGroupdJobId = It.IsAny<int>()
    }
};

您没有正确使用 Moq's It 匹配器。匹配器旨在用于 Moq 的 SetupVerify 调用(例如 see here 示例用法)

  • 在安排中,您不应该在创建虚假数据时使用 It.IsAnyIt.IsAny<> 将发生的所有事情是将分配值 default(Type),即 Ints 等为零,这不会有用。

var people = new List<DB.Person>
 {
   new DB.Person
   {        
       PeopleId = 1234, // Some traceable value and NOT It.IsAny<int>(),
       PersonGroupdJobId = 987,
       ...
  • 在 act 步骤中,您需要使用执行场景的值调用被测方法(同样,不仅仅是 It.IsAny<>):

var result = _repository.ListOfPeople(1234, 567); // Filters matching your test scenario

此外,由于被测试的方法至少有两个问题,即对存储库应用过滤器,然后将数据库实体映射到另一个 POCO,您需要提供一组完整的输入数据,以便您可以证明所有输入字段都映射到输出字段。

如果将所有这些放在一起,您的单元测试将类似于:

[Test]
public void ListOfPeople_peopleExist_returnsList()
{
    // Arrange : Generate fake data
    var people = new List<DB.Person>
    {    
        new DB.Person
        {
            PersonId = 123,
            PersonName = "Bob",
            PrimaryLanguage = "French",
            WorkTypeId = 987,
            PeopleGroups = new []
            {
                new DB.PeopleGroup
                {
                    AddressId = 123,
                    PersonGroupJobId = 999,
                    PeopleId = 123, // Match the parent ID
                    ProjectPartyId = 3
                }
            }
        }
    };

    // Your _unitOfWork and _repository mocks seem to be class private fields
    var _unitOfWork = new Mock<IUnitOfWork>();

    _unitOfWork
        .Setup(mock => mock.GetRepository<DB.Person>().GetAll())
        .Returns(people.AsQueryable());

    var _repository = new MyRepo(_unitOfWork.Object);

    // Act
    var result = _repository.ListOfPeople(123, 999);

    // Assert
    Assert.IsNotNull(result);
    Assert.AreEqual(1, result.Count(r => r.Name == "Bob" 
                                         && r.Id == 123 
                                         && r.PeopleGroups.First().Id == 3));
  //... etc - ensure all the fields are mapped 

    _unitOfWork.Verify(mock => mock.Commit(), Times.Never());
    _unitOfWork.Verify(mock => mock.GetRepository<DB.Person>().GetAll(), 
                       Times.Once());
}