Ayende @ Rahien

Hi!
My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 5,972 | Comments: 44,509

filter by tags archive

Rhino Mocks Futures


I have been thinking about this for a while now, and I am getting ready to release Rhino Mocks 3.5. The major feature is taking advantage on C# 3.0 language features. This allow some really interesting experimentation.

var mockedSmsSender = mocks.ToBeNamedMocked<ISmsSender>();
var mockedRepository = mocks.ToBeNamedMocked<IUserRepository>();
mockedRepository.Stub( x=> x.GetUserByName("ayende") ).Return( new User{Name="ayende", Pass="1234"});

new LoginController(mockedSmsSender, mockedRepository ).ForgotYourPassword("ayende");

mockedSmsSender.Verify( x => x.Send("ayende, your pass is 1234");

A few things to note about this code.

  • No explicit record / replay model
  • Arrange Act Assert model
  • You can setup return values by using Stub()
  • You can setup expectations using Expect(), with the same syntax
  • More complex verification is also possible.
  • I don't know what to call this new mode

As an aside, I am deprecating CreateMock in favor of StrictMock. Using strict mocks by default was a bad design decision on my part.

Thoughts?


Comments

Stuart C

I really like the Arrange Act Assert model, the syntax is great too. Why .ToBeNamedMocked<> as oposed to just .ToBeMocked<>? Seems strange, too many verbs...

Ayende Rahien

Stuart,

That is a temporary name because I don't know what to call this.

Graham

I think the rename from CreateMock to StrictMock is a good idea. I use DynamicMock regularly and this makes the difference more explicit.

I also like the idea of being able to create stubs on the fly. Sometimes a stub is all you need and it is convenient for it to be in the same framework as the mocking.

I look forward to this new version (as soon as Resharper supports .NET 3.0).

Andrew Davey

I really like the idea of verifying what I expected to happen after I have invoked my SUT. It's much nicer than the currently divided Expect and Verify.

I like to read tests as: Do X with SUT, assuming it did the following, assert these facts.

Stuart C

Ahhh, I get it. Now it makes sense. :)

Andrey Shchekin

I am really interested how would you solve the expectations that do not care about some of the arguments. I have done a similar thing for NMock2,

Expect.Once.That(() => mock.GetUserByName("ayende")).WillReturn(new User{Name="ayende", Pass="1234"});

but this obviously do not allow any matchers for "ayende" except for the default (equality? sameness?) matcher.

I was thinking about

Expect.Once.That(() => mock.GetUserByName(Any.String.StartingWith("ayende"))).WillReturn(new User{Name="ayende", Pass="1234"});

This would be parseable and compile if Any.String.StartingWith() (and Any.String if you do not care) were convertible to string. But I never got to implement this.

So I am looking forward how you solve that -- which would probably make me abandon NMock2 (for now, I like expect-that-willreturn more than stub-return, since it is a more natural language).

Ayende Rahien

mockedSernder.Verify( x => x.Send( Arg.Matching( s => s.StartsWtih("a") )

Oran

If I'm picturing this correctly, I'm thinking of the new mode as "modeless/stateless stub mode" where you can opt into stricter behavior verification and possibly opt into the record-replay model as well.

How about CreateStub, StubMock, ModelessMock, or StatelessMock? Or perhaps an overload of CreateMock or DynamicMock with a config enum, or a new method simply named Mock that takes a config enum for returning all of the various mock types. It would also be nice to have the option of turning on property behavior if it's not on by default.

Thomas Eyde

This looks similar to Moq. However, I have only seen blog posts about Moq, never tried it myself. But it looks cool. When there are several, but similar frameworks available, it would be nice to know why or when Rhino Mock would be the better choice. In other words, I'd like some marketing, please.

Krzysztof Koźmic

I'd recommend moving ALL mock creation methods to one method, and just pass parameters to it. It makes API cleaner, and easier to use.

public T CreateMock(params object[] argumentsForConstructor);

public object CreateMock(Type type, params object[] argumentsForConstructor);

public T CreateMockWithRemoting(params object[] argumentsForConstructor);

public object CreateMockWithRemoting(Type type, params object[] argumentsForConstructor);

public T CreateMultiMock(params Type[] extraTypes);

public object CreateMultiMock(Type mainType, params Type[] extraTypes);

public T CreateMultiMock(Type[] extraTypes, params object[] argumentsForConstructor);

public object CreateMultiMock(Type mainType, Type[] extraTypes, params object[] argumentsForConstructor);

public T DynamicMock(params object[] argumentsForConstructor);

public object DynamicMock(Type type, params object[] argumentsForConstructor);

public T DynamicMockWithRemoting(params object[] argumentsForConstructor);

public object DynamicMockWithRemoting(Type type, params object[] argumentsForConstructor);

public T DynamicMultiMock(params Type[] extraTypes);

public object DynamicMultiMock(Type mainType, params Type[] extraTypes);

public T DynamicMultiMock(Type[] extraTypes, params object[] argumentsForConstructor);

public object DynamicMultiMock(Type mainType, Type[] extraTypes, params object[] argumentsForConstructor);

public static T GenerateStub(params object[] argumentsForConstructor);

public static object GenerateStub(Type type, params object[] argumentsForConstructor);

public T PartialMock(params object[] argumentsForConstructor) where T: class;

public object PartialMock(Type type, params object[] argumentsForConstructor);

public T PartialMultiMock(params Type[] extraTypes);

public T PartialMultiMock(Type[] extraTypes, params object[] argumentsForConstructor);

public object PartialMultiMock(Type type, params Type[] extraTypes);

public object PartialMultiMock(Type type, Type[] extraTypes, params object[] argumentsForConstructor);

public T Stub(params object[] argumentsForConstructor);

public object Stub(Type type, params object[] argumentsForConstructor);

Right now those are all methods that create some kind of mock. (v3.4). I guess that having one or two methods like

public TType Mock();

public TType Mock(MockKind kind);

public TType Mock(MockKind kind, params Type[] extraTypes);

public TType Mock(MockKind kind, params object[] ctorArgs);

public TType Mock(MockKind kind, Type[] extraTypes, params object[] ctorArgs);

Would make it cleaner, less scary for newcomers and easier to strart with.

Benny Thomas

I agree with Krzysztof.

You should have seperated Remoting, Multi, Dynamic, Partial to its own Classes and let them each implement their own:

public TType Mock();

public TType Mock(MockKind kind);

public TType Mock(MockKind kind, params Type[] extraTypes);

public TType Mock(MockKind kind, params object[] ctorArgs);

public TType Mock(MockKind kind, Type[] extraTypes, params object[] ctorArgs);

Krzysztof Koźmic

@Benny

I actually had something else in mind.

Take a look at this: http://kozmic.pl/archive/2008/04/21/simplifying-rhino.mocks.aspx

Ben Scheirman

I was thinking about this exact implementation during the mocking session at alt.net.

I like it, however one area that will suffer is if you have a failed expectation you cannot know to throw an exception.

Other than that, it's a good feel.

(oh and -1 for the name, I think we can do better)

I don't fully agree with mocks.Mock(MockType.Scrict) .... that doesn't read well.

Alex Simkin

@Ayende

"I am deprecating CreateMock in favor of StrictMock"

then you should deprecate DynamicMock in favor of RelaxedMock or even NonStrictMock

Krzysztof Koźmic

@Ben

How would you call it then? Oh, and version on my blog has changed MockKind to be just shorter: Kind, so you'd have

var foo = repo.Mock(Kind.Strict);

And as for the method name

Its supposed to create mocks so I think this name suits the purpose.

"Mock (as verb) IFoo for me please, as for the details I want it to be Strict with no additional parameters".

Ulu
Ulu

Will the new model be totally unusable in VB?

It has lambdas as well, but not those that return void ;(

ulu

Ayende Rahien

The current syntax will still work, so you wouldn't run into any issues

Benny Thomas

@Krzysztof

I have a long way to go and did answer kind of fast without looking @ the code and understanding what was going on.

I like your solution, simple and good. But I dont like to pass the kind as a parameter. But I confess that I dont know much about mocking and are @ an early point in learning when to use it. Do one mix all kinds of mocks in a test? Or do one tend to only use one kind of mock when testing?

I would prefer: (I have removed the redudant kind parameter)

public TType Mock();

public TType Mock(params Type[] extraTypes);

public TType Mock(params object[] ctorArgs);

public TType Mock(Type[] extraTypes, params object[] ctorArgs);

But I understand that if you mix several different kinds of mocks in one fixture, this is not an optimal solution.

So your solution seems very elegant.

@Ayende:

I see you are worried that you break your api. But I would say that you only use one mocking version in a project. So if the next version breaks the api, i would first use it in the next project and don't worry that the old api is broken. This is only for test and not for "production".

Benny

Morten Lyhr

Maybe its just me, but I dont understand why I have to declare the mock kind up front?

Usually I have a single Init() method that creates all dependencies as DynamicMock(). And then I have a FactoryMethod that creates the SUT.

Then if I have a test that needs another mock kind I override the instance and call the factory method again.

Something like:

public class LoginPresenterFixture

{

private MockRepository _mockRepository;

private LoginPresenter _loginPresenter;

private LoginView _loginView;


[SetUp]

public void Init()

{

    _mockRepository = new MockRepository();

    _loginView = _mockRepository.DynamicMock<LoginView>();

    CreateLoginPresenter();

}


private void CreateLoginPresenter()

{

    _loginPresenter = new LoginPresenter(_loginView);

}


[Test]

public void Dynamic_Test_Usually_The_Way_To_Go()

{

    using (_mockRepository.Record())

    {

        Expect.Call(_loginView.ShowView);

    }

    using (_mockRepository.Playback())

    {

        _loginPresenter.Show();

    }

}


[Test]

public void Strict_Test_Not_As_Often_Used()

{

    //Override default mock kind

    _loginView = _mockRepository.CreateMock<LoginView>();

    CreateLoginPresenter();


    using (_mockRepository.Record())

    {

        Expect.Call(_loginView.ShowView);

    }

    using (_mockRepository.Playback())

    {

        _loginPresenter.Show();

    }

}

}

Know as far as I am concerned I only need 1 mock creation method. (DynamicMock).

What I really need is the ability to change the kind in each test.

Something like:

public class LoginPresenterFixture

{

private MockRepository _mockRepository;

private LoginPresenter _loginPresenter;

private LoginView _loginView;


[SetUp]

public void Init()

{

    _mockRepository = new MockRepository();

    _loginView = _mockRepository.DynamicMock<LoginView>();

    _loginPresenter = new LoginPresenter(_loginView);

}


[Test]

public void Dynamic_Test_Usually_The_Way_To_Go()

{

    using (_mockRepository.Record())

    {

        Expect.Call(_loginView.ShowView);

    }

    using (_mockRepository.Playback())

    {

        _loginPresenter.Show();

    }

}


[Test]

public void Strict_Test_Not_As_Often_Used()

{

    //Override default mock kind

    _mockRepository.StrictMockBehaviour(_loginView);

    using (_mockRepository.Record())

    {

        Expect.Call(_loginView.ShowView);

    }

    using (_mockRepository.Playback())

    {

        _loginPresenter.Show();

    }

}

}

Ayende Rahien

There is not technical reason not to do that.

I think it would be confusing, though

Morten Lyhr

Confusing?

This way you can read what mock kind it is in the test, you dont have to scroll to the init method to figure out the kind.

Daniel Cazzulino

It's good to see MoQ (http://mockframeworks.com/moq) ideas implemented in Rhino. I believe this is the right thing to do, as it lowers the barrier of entry for people getting into unit testing and mocking.

I'm glad that we're finally getting past the "... the record, replay, verify model stands at the core of mocking." (http://ayende.com/Blog/archive/2007/12/26/The-RecordReplayVerify-model.aspx) and we start thinking about what real users find easier to use.

The future is looking good for mocking!

:)

Krzysztof Koźmic

@Morten

I like your idea, though not your implementation.

It'd be easier to implement but I find the idea of 'overriding' the actual mock object not very intuitive.

What do you think about doing things in similar way to the following:

On the surface having just one kind of mock: DynamicMock

You'd write your tests in a usual way, and having additional helper methods to change the mock behaviour for that particular test:

  • Expect.For(_loginView).NothingElse(); //- this would set your mock in a strict mode (as if it was created with _repo.CreateMock();

  • Expect.For(_loginView).AnythingElse();//- this would create a stub

  • Expect.For(_loginView).AnythingForwardCalls(); // I dont like the name, but something like this for partial mocks.

Anyway, the main idea is not to change the mock type, but mock behaviour, as this is what actually matters.

However I'm not sure how deep changes would be required to implement this.

Comment preview

Comments have been closed on this topic.

FUTURE POSTS

  1. Paying the rent online - 2 hours from now
  2. Reducing parsing costs in RavenDB - about one day from now

There are posts all the way to Aug 04, 2015

RECENT SERIES

  1. Production postmortem (5):
    29 Jul 2015 - The evil licensing code
  2. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
  3. API Design (7):
    20 Jul 2015 - We’ll let the users sort it out
  4. What is new in RavenDB 3.5 (3):
    15 Jul 2015 - Exploring data in the dark
  5. The RavenDB Comic Strip (3):
    28 May 2015 - Part III – High availability & sleeping soundly
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats