Rhino Mock列表约束

7

我想要断言一个存根(stub)上的方法被调用。我要断言的方法需要传入一个 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"作为限制条件添加。我错过了什么?

2个回答

11
问题出在延迟执行上。只有当枚举时,项目列表才会“构建”。由于Rhino.Mocks仅记录调用的内容,它从未“使用”方法参数,因此列表既未构建也未枚举。如你所见,添加ToList()或ToArray()可枚举和构建列表,因此如果使用其中一种方法,则测试将通过。
一种解决方法是获取传递给方法的列表,并在其上进行检查。
var list = (IEnumerable<int>) myBob.GetArgumentsForCallsMadeOn(b => b.DoThings(null))[0][0];
Assert.AreEqual(10, list.Count());

这个测试通过,不需要对你的代码做任何更改。


Patrick,我之前不知道GetArgumentsForCallsMadeOn()方法。现在我可以写一个有意义的断言了。最近好像经常出现延迟执行问题。谢谢。 - Stealth Rabbi

2

这个问题已经在这里报告过了。我已经用以下的Bob和Joe重现了这个问题:

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

看起来Rhino Mocks在处理LINQ时存在一些问题:要么向Ayende报告错误,要么在生产代码中添加ToList()方法(不推荐)...


很奇怪...如果我在MethodThatShouldCallDoThingWith10中设置断点,我可以看到bob实例是一个代理,并且正在进行调用。显然这不是我的真正代码,但是是的,我认为我的问题有些棘手,但我无法确定具体原因。 - Stealth Rabbi
你可以开始简化它... Bob 是一个接口吗?抽象类?还是带有虚拟方法的类? - Amittai Shapira
这是一个带有通用类型的接口...一个Bob<T>。我在想被测试单元是否使用了WhereSelectIterator<T>来调用MethodThatShouldCallDoThingWith10,而不是像List<T>或简单的IEnumerable<T>这样更基本的东西。我认为Count约束并不那么宽容? - Stealth Rabbi
1
它通过了10,但作为WhereSelectIterator也通过了。 - Stealth Rabbi
让我们在聊天中继续这个讨论。点击此处进入聊天室 - Amittai Shapira
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接