使用Moq安排单元测试
本文关键字:单元测试 Moq 使用 | 更新日期: 2023-09-27 18:02:45
我创建了一个名为ListOfPeople
的方法,并试图为它编写一个单元测试。目前,我在设置单元测试的Arrange
部分时遇到了麻烦。我现在不能运行它,因为我的PeopleId
和PersonGroupJobId
状态是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's
It
匹配器。匹配器用于Moq的Setup
和Verify
调用(例如,参见这里的示例用法)
- 在这种情况下,在创建假数据时不应该使用
It.IsAny
。It.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>()
}
};