Ayende @ Rahien

It's a girl

Recursive Mocking

This now works :-)

image

The challenge is still open, I intentionally stopped before completing the feature, and there is a failing test in the RecusriveMocks fixture that you can start from.

And just to give you an idea about what I am talking about, please run this and examine the results:

svn diff https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk -r 1682:1683

A really cool web view of them is here.

Comments

John Chapman
10/10/2008 12:37 PM by
John Chapman

Ayende,

This is truly awesome. This will be a godsend for a lot of my work. I almost wish I was unemployed right now so that I had the time to finish this up for you. Maybe if nobody gets to it by next weekend, I'll have a shot at it.

Any idea what the planned release schedule is to include this feature?

John Chapman

Chad Myers
10/10/2008 02:12 PM by
Chad Myers

Ayende, thank you for your contribution here (and Roy's in his project), but I still think that, while this is a neat technical feature, it will encourage/allow people to get themselves into some big problems.

I follow the idea that mocking large, complicated API's like ICriteria, ADO.NET, HttpContext, etc is wrong. And not just because it was a big hassle (which you and Roy have already fixed), but because I feel large API's should be wrapped very tightly and tested via integration (since unit testing tightly-wrapped APIs is ultimately just testing the underlying API which I'm not interested in).

In my practice, I'm going to advise people to not use this feature unless there's some special circumstance that warrants it for some reason.

Was there a specific use case that has driven this feature in both TM and RM that I'm perhaps not thinking of?

Or was it just friendly competition among colleagues (Roy & Ayende)? :) :) :)

Ayende Rahien
10/10/2008 02:17 PM by
Ayende Rahien

The reasoning is as follows:

a/ I get a lot of questions about that

b/ It is a neat feature

c/ It helps greatly in some scenarios.

There are plenty of things in Rhino Mocks that can be abused, that doesn't mean that they aren't valuable. I don't really believe in taking away options.

Chad Myers
10/10/2008 02:20 PM by
Chad Myers

@Ayende:

I agree you should not take it away. I'm appreciative of you and Roy for taking the time to add this. It will definitely be useful in certain circumstances. But, like I was telling Roy, I believe there should be some heavy guidance around this type of feature warning people that this should be used only in special circumstances.

Ayende Rahien
10/10/2008 02:23 PM by
Ayende Rahien

Chad,

No argument about that from me.

Will you be willing to write that guidance for Rhino Mocks' documentation?

Vladan Strigo
10/10/2008 02:47 PM by
Vladan Strigo

Just one small comment about my specs in that docs... they are based on an older version of Rhino Mocks (pre AAA style version) and the fancy usings are just wrapping up the Record/Replay model.

Cheers!

Vladan

Chad Myers
10/10/2008 02:54 PM by
Chad Myers

@Ayende: I promised Roy I'd do it for him, I suppose I should afford you the same courtesy.

Should I put it in the wiki, or do you have something in SVN?

Ayende Rahien
10/10/2008 02:59 PM by
Ayende Rahien

thanks,

the wiki would be great

pb
10/11/2008 04:56 AM by
pb

The first test passes and the second doesn't. is that as you expect?

    [Test]

    public void CanCallSomeRandomInterfacePropertyWithReturn()

    {

        var mockService = MockRepository.GenerateMock

<imyservice();

        mockService.Expect(x => x.Identity.Name).Return("foo");

        Assert.AreEqual("foo", mockService.Identity.Name);

    }


    [Test]

    public void CanCallSomeRandomInterfacePropertyWithReturn2()

    {

        var mockService = MockRepository.GenerateMock

<imyservice();

        Expect.Call(mockService.Identity.Name).Return("foo");


        Assert.AreEqual("foo", mockService.Identity.Name);

    }
Ayende Rahien
10/11/2008 05:12 AM by
Ayende Rahien

pb,

Yes, that is the expected behavior.

Expect.Call() can only be used with mocks in record mode.

the static methods on MockRepository are generating mocks in replay mode.

If you want to deal with them, you need to use the Expect() or Stub()

pb
10/11/2008 12:28 PM by
pb

In your first post, the example you posted as needing development in order to work was the second one. The first test is what now works after getting the latest code after your mod. So have you revised the requirements that you expect it to work only in the first scenario but not the second? Because my understanding was that you wanted the second to work.

Ayende Rahien
10/11/2008 12:30 PM by
Ayende Rahien

pb,

Yes, sorry.

I posted about what I wanted, but that was fuzzy at the edges.

Ideally, I would want to get that to work.

The problem is that this is not really possible, I don't have the seam to be able to tell when Expect.Call( expression ) is called, so I don't know how to differentiate between that at just expression

pb
10/11/2008 07:44 PM by
pb

Ok, that clears things up. So the only thing remaining in your request is to make sure that the auto mocked instances are the same object then?

Ayende Rahien
10/11/2008 07:47 PM by
Ayende Rahien

pb,

Yes, that is the main thing.

Of course, trying to add more tests will likely create additional failure points.

pb
10/12/2008 03:48 PM by
pb

In case anyone else looks at this, the first one passes, the second one doesn't. So either the replay is coincidentally returning the same mocked instance or that is the intent and it just needs to work when not in replay mode. I'll take another look during the week sometime.

    [Test]

    public void WillGetSameInstanceOfRecursedMockInReplayMode()

    {

        MockRepository mocks = new MockRepository();

        var mock = mocks.DynamicMock

<imyservice();

        mocks.Replay(mock);


        IIdentity i1 = mock.Identity;

        IIdentity i2 = mock.Identity;


        Assert.AreSame(i1, i2);

    }


    [Test]

    public void WillGetSameInstanceOfRecursedMockWhenNotInReplayMode()

    {

        MockRepository mocks = new MockRepository();

        var mock = mocks.DynamicMock

<imyservice();

        IIdentity i1 = mock.Identity;

        IIdentity i2 = mock.Identity;


        Assert.AreSame(i1, i2);

    }
Comments have been closed on this topic.