2011-09-22 122 views
7

我试图说明一个方法在存根上被调用。我试图断言的方法被称为IEnumerable<string>。我不在乎确切的内容,但我只想测试计数是一定的数字。我不能断言是正确的,我得到犀牛模拟列表约束

Rhino.Mocks.Exceptions.ExpectationViolationException : Bob.DoThings(collection count equal to 10); Expected #1, Actual #0. 

我知道DoThings()的确是被称为...我只是不能得到正确的约束..

var myBob= MockRepository.GenerateStub<Bob>(); 
var countConstraint = Rhino.Mocks.Constraints.List.Count(Rhino.Mocks.Constraints.Is.Equal(10)); 

// execution code.... 
Joe myJoe = new Joe(myBob); 
myJoe.MethodThatShouldCallDoThingWith10(); 

myBob.AssertWasCalled(s => s.DoThings(null), o => Constraints(countConstraint)); 

我我们也尝试添加“IgnoreArguments”作为约束条件。我错过了什么?

回答

11

这里的问题是推迟执行。直到IEnumerable<string>列举项目列表是“内置的”。由于Rhino.Mocks只记录被调用的内容,因此它永远不会“使用”方法参数,因此列表不会被构建也不会枚举。正如你所看到的,添加一个ToList()或ToArray()枚举并建立列表,这样如果你使用其中一种方法,测试就会通过。

一个解决办法就是抓住传递给方法,做你的支票上,该清单:

var list = (IEnumerable<int>) myBob.GetArgumentsForCallsMadeOn(b => b.DoThings(null))[0][0]; 
Assert.AreEqual(10, list.Count()); 

该测试通过,不需要对代码进行任何更改。

+0

Patrick,I没有意识到GetArgumentsForCallsMadeOn()方法。我能够在这里写出一个有意义的断言。迟到的执行问题似乎在最近经常出现。谢谢。 –

2

此问题已报告Here。我已经能够重现此问题有以下鲍勃和乔:

public interface Bob 
{ void DoThings(IEnumrable<int> list); } 

public class Joe 
{ 
    private readonly Bob bob; 

    public Joe(Bob bob) 
    { this.bob = bob; } 

    public void MethodThatShouldCallDoThingWith10() 
    { 
      var values = Enumerable.Range(1, 100).Where(x => x > 0 && x < 11); 
      bob.DoThings(values); 
    } 
} 

似乎有在犀牛嘲笑一些问题,毕竟,当它涉及到LINQ:要么缺陷报告给Ayende或添加ToList( )在您的生产代码(不是真的推荐)...

+0

我很奇怪......如果我在MethodThatShouldCallDoThingWith10中放置一个断点,我可以看到bob实例是一个代理,并且正在进行呼叫。很明显,这不是我的真实代码,但是,我认为在我的结尾有些事情可以做到,但是我不能把手指放在它上面 –

+0

你可能会开始简单地使用它...... Bob是一个界面吗?抽象类?带虚拟方法的类? –

+0

我用一个通用接口... a Bob 。我想知道被测单元正在使用WhereSelectIterator 调用MethodThatShouldCallDoThingWith10,而不是像列表或简单的IEnumerable 那样更基本。我在考虑Count约束不是那么宽容吗? –