如何 return 使用 Moq 模拟对象中的实际对象

How to return the actual object from a mocked object with Moq

假设我有这个被嘲笑的方法:

public Comfirmation AddCustomer(Customer customer)
{ 
   // add customer to the Database
   return confirmation;
}

我的模拟是这样的:

_service
.Setup(x =>x.AddCustomer(It.IsAny<Customer>))
.Returns(new Confirmation());

如何从实际方法中获取确认对象/状态? 我知道模拟的目的是隔离影响代码行为的外部因素,但我确实需要获得实际方法的计算结果。因为这个结果会用在其他一些测试中。

Moq 不执行 class 的 AddCustomer 函数。因此,您当前的 Moq 设置无法获取 Confirmation 对象,可能已经创建了 AddCustomer 的真正实现。

如果您需要 Confirmation 作为另一个测试的输入,那么测试的 arrange 部分的作用是为方法创建输入参数正在测试中。

如果您通过调用 AddCustomer 函数来解决此问题,那么您会创建 创建代码和正在使用的代码的 耦合 确认书。如果创建代码更改,测试可能会在其他区域中断,并且调试原因可能很困难且耗时

对于集成测试,这种耦合是正确的选择,因为您要测试软件的两个部分之间的交互。对于单元测试,我建议将 AddCustomer 功能与其他部分分离。

另一种方法是创建 Confirmation 可能已创建 AddCustomer 函数的对象。这可以通过一些 capture/replay 方法手动完成或对于更复杂的对象(例如,将合适的 Confirmation 对象从 AddCustomer 函数序列化为 XML 或 JSON并通过反序列化器解析静态 XML 或 JSON 字符串,为其他测试中的模拟创建 Confirmation 对象。例如

 string capturedJson = "...."; // <= JSON of a Confirmation object
 var confirmation = JsonConvert.DeserializeObject<Confirmation>(capturedJson);
 _service
    .Setup(x =>x.AddCustomer(It.IsAny<Customer>))
    .Returns(confirmation);

 target.SomeConfirmationObjectUsingFunction(_service);