Mocking, virtual and more
This question would have been asked many times w.r.t to RhinoMocks, but I will try to present a little differently. I have a situation like this below -
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;
}
}
Mocking: Now, I want to do something like this -
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();
Error: Invalid call, the last call has been used or no call has been made (make sure that you are calling a v开发者_开发知识库irtual (C#) / Overridable (VB) method).
Problem is that, the concrete class B is being accessed in ctor of A for accessing the Property. How do I handle this scenario in RhinoMocks ? If I make the propeerty Foo as virtual, it works fine. But, I do not want to do that.
First, check your exception stack trace, and see where the "invalid call" error is coming from. Does it come from the Expect.Call
line? If so, remove the A
class from the picture.
Second, all mocking frameworks need a way to check if a property/method has been called. They replace the regular property/method code with some code that records how the call happened. In order to replace code, a mocked property or method must be virtual or abstract, or the mock should be created for an interface.
If a property needs to be mocked, and its original behaviour can't be mocked away, here's one alternative. You move the code from B.Foo
into a new property, and create a virtual dummy replacement for B.Foo
.
class B
{
// Old code here
public bool RealFoo { get { return status; } }
// New dummy code
public virtual bool Foo { get { return RealFoo; } }
}
Then from your mocking code, you can record when Foo
gets called, and you can call the "real" code too:
var myObjB = mock.StrictMock<B>();
Expect.Call(myObjB.Foo).Return(myObjB.RealFoo);
精彩评论