2010-06-15 64 views
1

我已经通读了Moq用户组的一些讨论,并且未能找到示例,并且迄今为止 无法找到我拥有的场景。这里是我的问题,代码:用Moq嘲笑收藏行为

// 6 periods 
var schedule = new List<PaymentPlanPeriod>() 
{ 
    new PaymentPlanPeriod(1000m, args.MinDate.ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(1).ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(2).ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(3).ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(4).ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(5).ToString()) 
}; 

// Now the proxy is correct with the schedule 
helper.Setup(h => h.GetPlanPeriods(It.IsAny<String>(), schedule)); 

然后在我的测试中,我使用期,但嘲笑_PaymentPlanHelper从未填充集合,请参阅下面的用法:

public IEnumerable<PaymentPlanPeriod> Periods 
{ 
get 
{ 
    if (CanCalculateExpression()) 
    _PaymentPlanHelper.GetPlanPeriods(this.ToString(), _PaymentSchedule); 

    return _PaymentSchedule; 
} 
} 

现在,如果我的嘲笑对象更改为使用GetPlanPeriods的另一种重载方法,它返回一个List,如下所示:

var schedule = new List<PaymentPlanPeriod>() 
{ 
    new PaymentPlanPeriod(1000m, args.MinDate.ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(1).ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(2).ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(3).ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(4).ToString()), 
    new PaymentPlanPeriod(1000m, args.MinDate.Value.AddMonths(5).ToString()) 
}; 

helper.Setup(h => h.GetPlanPeriods(It.IsAny<String>())).Returns(new List<PaymentPlanPeriod>(schedule)); 

List<PaymentPlanPeriod> result = new _PaymentPlanHelper.GetPlanPeriods(this.ToString()); 

这个按预期工作。任何指针将是真棒,只要你不想揍我的建筑... :)

谢谢 斯蒂芬

+1

我是否正确,您希望您的模拟方法调用来修改传递给它的计划参数?这个SO问题可能会有所帮助 - 答案使用回调http://stackoverflow.com/questions/2183691/how-to-modify-an-invocation-parameter-of-a-mocked-method-with-moq – 2010-06-15 23:18:25

+0

是的大卫。我正在阅读其他帖子。谢谢。 – 2010-06-15 23:57:41

回答

4

的设置,方法基本设置一些expeced行为。例如,设置一个模拟实例来返回某些值。例如配置,模拟:

var configMock = new Mock<IConfiguration>(); 
configMock.Setup(c=>c.GetSetting("Title")).Returns("Hello Word"); 
configMock.Setup(c=>c.GetSetting("Answer")).Returns("42"); 

这意味着,比当你通过“标题”对GetSetting法模拟将返回“你好词”。当你通过“回答”模拟,它会返回“42”。你可以添加配置通配符。例如:

var configMock = new Mock<IConfiguration>(); 
configMock.Setup(c=>c.GetSetting(It.IsAny<String>())).Returns("Hello Word"); 

现在模拟将返回到GetSetting-方法的调用将字符串“Hello World”

现在,在你的第一个情况下,你设置了模拟了这种方式:期待一个电话GetPlanPeriods与任何字符串和此列表。因此,用第二个参数指定您期望的列表。但是你没有为这个电话设置任何行动。

Afaik你可以设置Moq与参数的东西。就像这样:

helper.Setup(c => c.GetPlanPeriods(It.IsAny<string>(),It.IsAny<List<PaymentPlanPeriod>>())) 
      .Callback((string s, List<PaymentPlanPeriod> l)=> 
          { 
           l.Add(new PaymentPlanPeriod(1000m, args.MinDate.ToString())); 
          }); 

在第二个例子中,你设置了模拟了这种方式:期待GetPlanPeriods调用任何字符串,然后返回这个列表。所以它会返回给定的列表的任何电话。那就是它的原因。

我一般我会建议你设计你的API的方式,你是第二个例子。倾向于返回已更改的集合,而不是更新已传递的集合。使用和嘲笑这种方法更容易。