我正在抄写两个不同的对象。以下是接口:
public IInterface1
{
IEnumerable<Foo> Method1(int p1, string p2 = null, string p3 = null);
}
public IInterface2
{
Bar Method2(int p3, int? p4 = null);
}
如您所见,两者都有默认为null的参数。但是,一个匹配我的Expect
,另一个不匹配。这个存根工作;当使用值匹配testData.p1
调用其方法时,它返回一个包含两个Foo
的数组:
var obj1 = MockRepository.GenerateStub<IInterface1>();
obj1.Expect(m => m.Method1(
Arg.Is(testData.p1),
Arg<string>.Is.Null,
Arg<string>.Is.Null))
.Return(new[] { new Foo(), new Foo() });
但是,这个类似的存根不返回预期的结果,而是返回null
,尽管参数符合预期:
var obj2 = MockRepository.GenerateStub<IInterface2>();
obj2.Expect(m => m.Method2(Arg.Is(testData.p3), Arg<int?>.Is.Null))
.Return(new Bar());
为什么第二个存根与我的参数不匹配?即使我使用Arg<int?>.Is.Anything
作为第二个预期参数,仍会返回null
。
更新
好的,我找到了另一种方法来设置我的期望,传递预期值而不是使用Arg
:
obj1.Expect(m => m.Method1(testData.p1, null, null))
.Return(new[] { new Foo(), new Foo() });
obj2.Expect(m => m.Method2(testData.p3, null))
.Return(new Bar());
当我以这种方式设置它们时,两个存根都会返回预期的结果。我仍然不清楚这种区别以及为什么一个人与Arg
合作而另一个人没有合作。我想这是另一个时间,我对这个库中的AAA,记录/重放,模拟和存根的混合感到困惑。任何人都可以消除我对原始代码不起作用的困惑吗?
答案 0 :(得分:2)
在运行时,当您将null传递给IInterface2
的第二个参数时,.NET将创建一个Nullable<int>
并将其传递给您的方法实现。然后,您的实现代码可以检查p4.HasValue并执行您想要考虑空值的任何内容。
但是从Rhino.Mocks的立场来看,当它拦截方法调用时,它会看到第二个参数是Nullable<int>
(不是空实例),因此你的期望不会匹配。 / p>
在第二次尝试中,当您直接传递null时,运行时将再次将该null包装在Nullable<T>
中。 Rhino.Mocks会检查两个参数是否相等(看看你是否有匹配的期望)。 Nullable<T>
会覆盖Equals
方法,以检查两个Nullable<T>
是否都为null并返回true - 从而符合您的预期。