如何在模拟对象内创建模拟对象?

How can I create a mocked object inside a mocked object?

我的代码中有这两行。

Customer customer = Repository.Customer.GetById(customerId);
Employee employee = customer.Employees.Single(e => e.IsPrimaryContact);

现在,我正在创建一个单元测试。对象、客户和员工都受到保护,所以我需要模拟它们。

我已经成功地模拟了第一个并创建了一个模拟对象 'customer' 作为它的 return 用于通过 Id 获取客户。

Customer customer = new Mock<Customer>().Object;
/* code ... code*/

var mockCustomerRepository = new Mock<ICustomerRepository>();
mockCustomerRepository.Setup(p => p.GetById(It.IsAny<Guid>())).Returns(customer);
Repository.Customer = mockCustomerRepository.Object;

如您所见,'employee' 对象位于模拟对象 'customer' 内,这意味着我还必须在我的第一个模拟对象 (Customer) 内提供一个模拟对象。我希望我的代码是这样的。

Employee employee = new Mock<Employee>().Object;
employee.IsPrimaryContact = true;

List<Employee> employees = new List<Employee>();
employees.Add(employee);

customer.Employees = employees;
/* code ... code*/

但是,虽然我在构建测试时没有任何错误。 customer.employee 始终为 NULL。

我建议你试试这个代码

Mock<Customer>() mockCustomer = new Mock<Customer>();
Employee employee = new Employee();
mockCustomer.Setup(x=>x.Employees).Returns(employee);
Customer customer = mockCustomer.Object;

Sethu Bala 的建议可能行不通,因为您无法设置非虚拟成员。

你能通过调用构造函数、生成器或诸如 AutoFixure 之类的工具来创建 Customer 和 Employee 吗?然后将您的存储库设置为 returns 这些对象。

var customer = CustomerBulder
    .WithEmployees(*list of employees*)
    .Build();
var mockCustomerRepository = new Mock<ICustomerRepository>();
mockCustomerRepository
    .Setup(p => p.GetById(It.IsAny<Guid>()))
    .Returns(customer);

如果不需要复杂的设置,请使用 Linq to Mocks Mock.Of<T> 获取模拟对象。它将允许分配 属性 值。

Employee employee = Mock.Of<Employee>();
employee.IsPrimaryContact = true;

List<Employee> employees = new List<Employee>();
employees.Add(employee);

Customer customer = Mock.Of<Customer>();
customer.Employees = employees;

var mockCustomerRepository = new Mock<ICustomerRepository>();
mockCustomerRepository.Setup(p => p.GetById(It.IsAny<Guid>())).Returns(customer);
Repository.Customer = mockCustomerRepository.Object;

现在应该按预期执行单元测试。