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
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...
Stuart,
That is a temporary name because I don't know what to call this.
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).
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.
Ahhh, I get it. Now it makes sense. :)
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).
mockedSernder.Verify( x => x.Send( Arg<string>.Matching( s => s.StartsWtih("a") )
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.
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.
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<T>(params object[] argumentsForConstructor);
public object CreateMock(Type type, params object[] argumentsForConstructor);
public T CreateMockWithRemoting<T>(params object[] argumentsForConstructor);
public object CreateMockWithRemoting(Type type, params object[] argumentsForConstructor);
public T CreateMultiMock<T>(params Type[] extraTypes);
public object CreateMultiMock(Type mainType, params Type[] extraTypes);
public T CreateMultiMock<T>(Type[] extraTypes, params object[] argumentsForConstructor);
public object CreateMultiMock(Type mainType, Type[] extraTypes, params object[] argumentsForConstructor);
public T DynamicMock<T>(params object[] argumentsForConstructor);
public object DynamicMock(Type type, params object[] argumentsForConstructor);
public T DynamicMockWithRemoting<T>(params object[] argumentsForConstructor);
public object DynamicMockWithRemoting(Type type, params object[] argumentsForConstructor);
public T DynamicMultiMock<T>(params Type[] extraTypes);
public object DynamicMultiMock(Type mainType, params Type[] extraTypes);
public T DynamicMultiMock<T>(Type[] extraTypes, params object[] argumentsForConstructor);
public object DynamicMultiMock(Type mainType, Type[] extraTypes, params object[] argumentsForConstructor);
public static T GenerateStub<T>(params object[] argumentsForConstructor);
public static object GenerateStub(Type type, params object[] argumentsForConstructor);
public T PartialMock<T>(params object[] argumentsForConstructor) where T: class;
public object PartialMock(Type type, params object[] argumentsForConstructor);
public T PartialMultiMock<T>(params Type[] extraTypes);
public T PartialMultiMock<T>(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<T>(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<TType>();
public TType Mock<TType>(MockKind kind);
public TType Mock<TType>(MockKind kind, params Type[] extraTypes);
public TType Mock<TType>(MockKind kind, params object[] ctorArgs);
public TType Mock<TType>(MockKind kind, Type[] extraTypes, params object[] ctorArgs);
Would make it cleaner, less scary for newcomers and easier to strart with.
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<TType>();
public TType Mock<TType>(MockKind kind);
public TType Mock<TType>(MockKind kind, params Type[] extraTypes);
public TType Mock<TType>(MockKind kind, params object[] ctorArgs);
public TType Mock<TType>(MockKind kind, Type[] extraTypes, params object[] ctorArgs);
@Benny
I actually had something else in mind.
Take a look at this: http://kozmic.pl/archive/2008/04/21/simplifying-rhino.mocks.aspx
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<IFoo>(MockType.Scrict) .... that doesn't read well.
@Ayende
"I am deprecating CreateMock in favor of StrictMock"
then you should deprecate DynamicMock in favor of RelaxedMock or even NonStrictMock
@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<IFoo>(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".
Will the new model be totally unusable in VB?
It has lambdas as well, but not those that return void ;(
ulu
The current syntax will still work, so you wouldn't run into any issues
@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<TType>();
public TType Mock<TType>(params Type[] extraTypes);
public TType Mock<TType>(params object[] ctorArgs);
public TType Mock<TType>(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
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<T>(). 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
{
}
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
{
}
There is not technical reason not to do that.
I think it would be confusing, though
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.
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!
:)
@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<IView>();
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