CallOriginalMethod

176 views
Skip to first unread message

ernst80

unread,
Feb 16, 2007, 11:51:50 AM2/16/07
to Rhino.Mocks
Hi Ayende,

I have a problem with CallOriginalMethod:

We need to mock an object and expect a method with some constraints on
the parameters. However it is necessary for the test, that the
original method is executed as well. I did not find a way yet to do
this with Rhino.Mocks.

This unit test (which is red) should explain what I mean:

public class MockedClass
{
public virtual void Method (string parameter)
{
//Something in this method must be executed
}
}

[Test]
[ExpectedException (typeof
(Rhino.Mocks.Exceptions.ExpectationViolationException))]
public void DeleteThisTest ()
{
MockRepository mockRepository = new MockRepository ();
MockedClass mock = mockRepository.CreateMock<MockedClass> ();

mock.Method ("expectedParameter");
LastCall.CallOriginalMethod ();

mockRepository.ReplayAll ();

mock.Method ("invalidParameter");

mockRepository.VerifyAll ();
}

Can you tell me what needs to be done in order to get this test to
green?

Best regards,
Ernst

Ayende Rahien

unread,
Feb 16, 2007, 1:02:54 PM2/16/07
to Rhino...@googlegroups.com
Currently, there is nothing that you can do in order to make this work.
Rhino Mocks will let you do either, but not both.

You can extend Rhino Mocks to allow this, I added a sample with your test passing:
https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/rhino-mocks/Rhino.Mocks.Tests/ExtendingRhinoMocks2.cs

ernst80

unread,
Feb 19, 2007, 2:18:44 PM2/19/07
to Rhino.Mocks
Hi Ayende,

thanks for the quick reply and the information. I especially like the
ErnstRepository ;-)

I have to admit that I did not notice the behaviour of
CallOriginalMethod until now because it's kind of implicit. For a user
of Rhino.Mocks it would be really cool if you could control this
behavior in the record state, by either splitting the old
CallOriginalMethod in something like a "new .CallOriginalMethod" and
an ".IgnoreMethodCall" method or by a separate method like
"CallOriginalMethodAndValidate". I could imagine that quite a few
people could use this feature, or maybe are not aware of this
behavior.

Do you think that you will include this in the future?

Best regards,
Ernst


On 16 Feb., 19:02, "Ayende Rahien" <aye...@ayende.com> wrote:
> Currently, there is nothing that you can do in order to make this work.
> Rhino Mocks will let you do either, but not both.
>
> You can extend Rhino Mocks to allow this, I added a sample with your test

> passing:https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/rhi...

Ayende Rahien

unread,
Feb 19, 2007, 2:42:07 PM2/19/07
to Rhino...@googlegroups.com
If I understand you correctly, you mean that using CallOriginalMethod will not create an expectation, contrary to most of the usages in Rhino Mocks, right?

ernst80

unread,
Feb 21, 2007, 1:33:23 PM2/21/07
to Rhino.Mocks
Hi,

yes, that's correct.

I can write my expectation as e.g.
LastCall.Constraints (Is.Equal ("SomeString")).CallOriginalMethod
();
and do not notice that my expectation is not verified. I actually
thought for a long time that this call is verified, and noticed the
real behaviour just recently. Therefore IMHO "CallOriginalMethod" is
pretty misleading.

The "DoNotVerifyThisCall" part of CallOriginalMethod should be stated
explicitly rather than doing it implicitly. Unfortunately this would
be a breaking change and would require to make CallOriginalMethod
obsolete and creating other methods for the new behavior.

What's your opinion on that matter?

Best regards,
Ernst

On Feb 19, 8:42 pm, "Ayende Rahien" <aye...@ayende.com> wrote:
> If I understand you correctly, you mean that using CallOriginalMethod will
> not create an expectation, contrary to most of the usages in Rhino Mocks,
> right?
>

Ayende Rahien

unread,
Feb 22, 2007, 2:08:02 AM2/22/07
to Rhino...@googlegroups.com
I understand what you mean, and I think that I agree.
Let me think about it a bit.

Ayende Rahien

unread,
Feb 24, 2007, 7:55:04 AM2/24/07
to Rhino...@googlegroups.com
I have obsoloted CallOriginalMethod, instead we have:

CallOriginalMethod(OriginalCallOptions.CreateExpectation)
CallOriginalMethod(OriginalCallOptions.NoExpectation)

ernst80

unread,
Feb 26, 2007, 2:12:11 PM2/26/07
to Rhino.Mocks
Hi Ayende,

wow, that was fast!

Unfortunately, the implementation does not behave as expected. The
following example simplifies the scenario:

public class MockedClass
{
public virtual void Method (string parameter)
{

if (parameter == null)
throw new ArgumentNullException ();

//Something in this method must be executed
}
}

[Test]
public void CallOriginalMethodProblem2 ()


{
MockRepository mockRepository = new MockRepository ();
MockedClass mock = mockRepository.CreateMock<MockedClass> ();

mock.Method (null);
LastCall.Constraints (Is.Equal ("parameter")).CallOriginalMethod
(OriginalCallOptions.CreateExpectation);

mockRepository.ReplayAll ();

mock.Method ("parameter");

mockRepository.VerifyAll ();
}

The ArgumentNullException is thrown in this case, although "parameter"
should be passed, as it was before the parameter was added to
CallOriginalMethod.

Could you please look into it?

Thanks, Ernst

Ayende Rahien

unread,
Feb 26, 2007, 2:53:25 PM2/26/07
to Rhino...@googlegroups.com
Interesting scenario, yes, I will check it.

Ayende Rahien

unread,
Mar 5, 2007, 9:42:02 PM3/5/07
to Rhino...@googlegroups.com
I am an idiot.
I am invoking the previous invocation!
Fixed, thanks for spotting this.

On 2/26/07, ernst80 <ernst.sc...@gmx.net> wrote:

ernst80

unread,
Mar 12, 2007, 5:45:34 PM3/12/07
to Rhino.Mocks
Hi Ayende,

Thanks for fixing this. This is definitely helpful to us.

When I tested the new implementation of CallOriginalMethod I went
across the following:

public class TestClass
{
public virtual void Method () { }
}

[Test]
public void TestName ()
{
MockRepository repository = new MockRepository ();
TestClass mock = repository.CreateMock<TestClass> ();

mock.Method ();
LastCall.CallOriginalMethod
(Rhino.Mocks.Interfaces.OriginalCallOptions.NoExpectation);

repository.ReplayAll ();
mock.Method ();
repository.VerifyAll ();

repository.BackToRecordAll ();

mock.Method ();
LastCall.Throw (new ApplicationException ());

repository.ReplayAll ();

try
{
mock.Method ();
Assert.Fail ();
}
catch (ApplicationException ex)
{
}
}

The test is green when I use OriginalCallOptions.CreateExpectation.

This test fails. I give it to you just as a feedback since I currently
do not need a different behavior. It it seems easy to work around it
with LastCall.IgnoreArguments ().CallOriginalMethod
(OriginalCallOptions.CreateExpectations) instead of using
using .NoException.

However it is not obvious to me why the mock has this behavior after
BackToRecord ();

Best regrads,
Ernst

On Mar 6, 3:42 am, "Ayende Rahien" <aye...@ayende.com> wrote:
> I am an idiot.
> I am invoking the previous invocation!
> Fixed, thanks for spotting this.
>

Ayende Rahien

unread,
Mar 12, 2007, 5:59:08 PM3/12/07
to Rhino...@googlegroups.com
That is because NoExpectations are handled in the interceptor level, not in the mock state layer, thanks for finding it out.

Ayende Rahien

unread,
Mar 14, 2007, 5:08:49 PM3/14/07
to Rhino...@googlegroups.com
Fixed, thanks.
Reply all
Reply to author
Forward
0 new messages