如何使用Moq从模拟对象返回实际对象

时间:2016-11-23 11:01:04

标签: c# moq

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

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

我的模仿是这样的:

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

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

1 个答案:

答案 0 :(得分:1)

Moq不会执行该类的AddCustomer功能。因此,您当前的Moq设置无法获取Confirmation对象,因此可能已创建AddCustomer的实际实现。

如果您需要Confirmation作为另一个测试的输入,那么它是测试的安排部分的角色,以便为测试中的方法创建输入参数。

如果您通过调用AddCustomer函数来解决此问题,则可以创建Confirmation创建代码的耦合以及使用确认的代码。如果创建代码发生更改,则测试可能会在其他区域中断,并且调试原因可能会非常困难且耗时。

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

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

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