使用 Moq 安排单元测试
Arranging Unit Test using Moq
我创建了一个名为 ListOfPeople
的方法,并尝试为其编写 单元测试 。目前,我在设置 单元测试 的 Arrange
部分时遇到问题。我现在不能 运行 因为我的 PeopleId
和 PersonGroupJobId
状态 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 的 Setup
和 Verify
调用(例如 see here 示例用法)
- 在安排中,您不应该在创建虚假数据时使用
It.IsAny
。 It.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());
}
我创建了一个名为 ListOfPeople
的方法,并尝试为其编写 单元测试 。目前,我在设置 单元测试 的 Arrange
部分时遇到问题。我现在不能 运行 因为我的 PeopleId
和 PersonGroupJobId
状态 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 的 Setup
和 Verify
调用(例如 see here 示例用法)
- 在安排中,您不应该在创建虚假数据时使用
It.IsAny
。It.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());
}