使用Moq安排单元测试

本文关键字:单元测试 Moq 使用 | 更新日期: 2023-09-27 18:02:45

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

问题: 如何成功测试此方法?

我的方法:

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());
    }

使用Moq安排单元测试

您没有正确使用Moq's It匹配器。匹配器用于Moq的SetupVerify调用(例如,参见这里的示例用法)

  • 在这种情况下,在创建假数据时不应该使用It.IsAnyIt.IsAny<>所发生的一切都是将值赋给default(Type),即int等为零,这将不会有用。

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

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

同样,由于正在测试的方法至少有两个关注点,即对存储库应用过滤器,然后将DB实体映射到另一个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());
}

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

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