对于 RhinoMocks ,这个问题会多次被问到,但我会尝试提出一些不同的看法。我有这样的情况 -
class A
{
X parentOfB;
A()
{
X parentOfB = someObj;
if(<something>)
{
B objB = parentOfB as B // NOTE THIS
if(objB.Foo) // call the property here
{
// some code ....
}
}
}
}
class B : X
{
// gets initialised to true somewhere in the program. Don't bother much
protected bool status ;
B() {}
// Property
public bool Foo
{
return status;
}
}
惩戒: 现在,我想做这样的事情 -
var mock = new MockRepository();
var myObjB = mock.StrictMock<B>();
// call Db class to populate the objB object and then set the expectation as
// below
// ...
// ...
Expect.Call(myObjB.Foo).Return(true);
mock.ReplayAll();
var objA = new A();
mock.VerifyAll();
错误: 呼叫无效,最后一次呼叫已被使用或未进行任何呼叫(确保您正在调用虚拟(C#)/可覆盖(VB)方法)。
问题是,在A的ctor中访问具体的类B以访问该属性。如何在 RhinoMocks 中处理这种情况?如果我将prooerty Foo视为虚拟,它可以正常工作。但是,我不想这样做。
答案 0 :(得分:3)
首先,检查您的异常堆栈跟踪,并查看“无效调用”错误的来源。它来自Expect.Call
行吗?如果是这样,请从图片中删除A
类。
其次,所有模拟框架都需要一种方法来检查是否已调用属性/方法。它们用一些记录调用发生方式的代码替换常规属性/方法代码。为了替换代码,模拟的属性或方法必须是虚拟的或抽象的,或者应该为接口创建模拟。
答案 1 :(得分:0)
如果某个属性需要被嘲笑,并且其原始行为无法被嘲笑,那么这里有一个替代方案。您将代码从B.Foo
移动到新属性中,并为B.Foo
创建虚拟虚拟替换。
class B
{
// Old code here
public bool RealFoo { get { return status; } }
// New dummy code
public virtual bool Foo { get { return RealFoo; } }
}
然后从您的模拟代码中,您可以记录调用Foo
的时间,并且您也可以调用“真实”代码:
var myObjB = mock.StrictMock<B>();
Expect.Call(myObjB.Foo).Return(myObjB.RealFoo);