Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,602
|
Comments: 51,232
Privacy Policy · Terms
filter by tags archive
time to read 1 min | 91 words

Note, this is a copy of the discussion that is taking place in the Rhino Mocks mailing list.

Now that I pushed all the current changes out, we need to start thinking about the next version. I am planning on seeing what kind of syntax I can get from the language using C# 3.0. As of yet, I don't have any concrete ideas about what should be done, so I am here to solicit ideas about what you want.

Syntax suggestions, patches, comments, etc are all welcome.

time to read 2 min | 371 words

Well, it is about that time again, I got enough changes to make a release worthwhile. It has been almost five months, and we got a whole bunch of stuff going on, including a lot of stuff from contributors. (Take that, one man project :-) ).

As usual, you can get it here and the source is available here.

It is interesting to note that a lot of people have stuck with Rhino Mocks 3.1, I guess that there is really no need to upgrade, if you get what you want...

Features, more features, glorious features!

  • Added CreateMockWithRemoting and DynamicMockWithRemoting to work around BCL bug when overriding a generic method with generic constraint.
    This is useful when you want to force Rhino Mocks to use Remoting proxies (usually it just guess and you don't deal with this). That is needed because at certain cases ( generic methods with generic constraints ) there is a bug in Reflection Emit that generate invalid code.
  • Mike Nichols  has added List.ContainsAll() constraint
  • Shawn Neal added the DoNotExpect syntax, which is clearer the Expect.Call().Repeat.Never(), it is certainly shorter.
  • Added trace writer with stack trace, should make it easier to track down strange mocking behavior. Now you can just enable logging and see all the method calls that are being made.
  • Guido van Loon supplied the Property.AllPropertiesMatch constraints
  • Making sure that recorders that wrap recorders will be merged if they contain only one element. Again, this is something that you are not supposed to understand unless you went deep into the code. Suffice to say that the behavior is easier to understand now.

Bugs, annoying bugs, stupid bugs!

  • Fixing issue with empty recorders nested in recorders that has expectations. If you don't get that, then rest assure, neither do I.
  • Demid Sukhovsky  fixed Rhino Mocks support for Out/Ref values using remoting proxies.
  • Fixing null reference exception when stubbing a class with protected setter.
  • Aaron Jensen fixed the validation message when you expect a method that accept a mock object as a parameter.
  • Aaron Jensen also fixed a bunch of my typos.
  • Steven Rockarts fixed a bunch more of my typos.
  • Fixed an issue with methods returning non primitive value types, such as UInt32
time to read 2 min | 245 words

I have the following piece of code:

protected override void DoClose()
{
    IDisposable dispoable = enumerator as IDisposable;
    if (dispoable != null)
        dispoable.Dispose();

    dispoable = enumerable as IDisposable;
    if(dispoable != null)
        dispoable.Dispose();
}

How do I verify that it correctly disposes both enumerator and enumerable when the method is called?

Here is the test that I wrote, it is using Rhino Mocks' Multi Mocks feature to generate a proxy that has more than a single implementation.

[Test]
public void WillDisposeInternalEnumeratorAndEnumerableWhenDisposed()
{
    MockRepository mocks = new MockRepository();
    IEnumerable<Row> enumerable = mocks.DynamicMultiMock<IEnumerable<Row>>(typeof(IDisposable));
    IEnumerator<Row> enumerator = mocks.DynamicMock<IEnumerator<Row>>();
    using(mocks.Record())
    {
        SetupResult.For(enumerable.GetEnumerator()).Return(enumerator);
        enumerator.Dispose();
        ((IDisposable)enumerable).Dispose();
    }
    using (mocks.Playback())
    {
        DictionaryEnumeratorDataReader reader =
            new DictionaryEnumeratorDataReader(new Dictionary<string, Type>(), enumerable);
        reader.Dispose();
    }
}

Simple, and to the point.

time to read 3 min | 496 words

Daniel and I are having an interesting discussion about mock frameworks, and he just posted this: What's wrong with the Record/Reply/Verify model for mocking frameworks.

Daniel also pulled this quote from the Rhino Mocks documentation:

Record & Replay model - a model that allows for recording actions on a mock object and then replaying and verifying them. All mocking frameworks uses this model. Some (NMock, TypeMock.Net, NMock2) use it implicitly and some (EasyMock.Net, Rhino Mocks) use it explicitly.

Daniel go on to say:

I find this record/replay/verify model somewhat unnatural.

I suggest that you would read the entire post, since this is a response to that. I just want to point out that I still hold this view. Mock frameworks all use this model, because verification is a core part of mocking.

The problem that I have with what Daniel is saying is that we seem to have a fundamental difference in opinion about what mocking is. What Daniel calls mocks I would term stubs. Indeed, Daniel's library, by design, is not a mock framework library. It is a framework for providing stubs.

Going a little bit deeper than that, it seems that Daniel is mostly thinking about mocks in tests as a way to make the test pass. I am thinking of those in terms of testing the interactions of an object with its collaborators.

This project does a good job of showing off how I think mocking should be used, and it represent the accumulation of several years of knowledge and experience in testing and using mocks. It also represent several spectacular failures in using both (hint: mocking the database when going to production may not be a good idea), from which I learned quite a bit.

Mocking can be abused to cause hard to change tests, so can other methods. Deciding to throw the baby with the bath water seems to be a waste to me. There is a lot of guidance out there about correct application of mocking, including how to avoid the over specified tests. The first that comes to mind is Hibernating Rhinos #1 web cast, which talks about Rhino Mocks and its usage.

Rhino Mocks can be used in the way that Daniel is describing. I would consider this appropriate at certain times, but I think that to say that this is the way it should be is a mistake. The Rhino Mocks web cast should do a good job in not only showing some of the more interesting Rhino Mocks features, but also where to use them.

To conclude, the record, replay, verify model stands at the core of mocking. You specify what you think that should happen, you execute the code under test and then you verify that the expected happened. Taking this to the limit would produce tests that are hard to work with, but I am in the opinion that taking a worst practice and starting to apply conclusions from that is not a good idea.

time to read 2 min | 224 words

Daniel has a very interesting post about how mocking can works in C# 3.0 (I don't like the term Linq for Mock, if you haven't noticed).

I wonder if he has used Rhino Mocks, from the description of mock frameworks in the post, it looks like he didn't.

At any rate, the syntax that he has there if quite interesting:

var mock = new Mock<IFoo>();
mock.Expect(x => x.DoInt(It.Is<int>(i => i % 2 == 0))).Returns(1);

The use of lambda as a way to specify expectations is cool, and as a way to specify constraints, flat out amazing.

You can do most of that with Rhino Mocks right now, I feel forced to point out.

IFoo foo = mocks.DynamicMock<IFoo>();
Expect.Call( () => foo.DoInt(0) )
	.Callback( (int i) => i % 2 == 0 )
	.Return(1);

We even have an Is.Matching constraint, that we can use instead:

Expect.Call( () => foo.DoInt(0) )
	.Constraints( Is.Matching<int>( i => i % 2 == 0) )
	.Return(1);

I guess we will just need to see what kind of cool stuff we still have in store for it.

Great job, Daniel.

I suggest that you would check this out. The Quick Start gives few more examples, and it is looking really nice.

By the way, for the horde of people who would like to "port" those examples to Rhino Mocks, we have a wiki... :-) 

time to read 1 min | 187 words

This came up with respect to MS MVC. The MS MVC team has decided to make some methods protected, and that makes testing using Rhino Mocks a bit of a pain.

Let us assume that I want test that the call to ProductController.Index() will render the "index.aspx" view. I can do something like:

[Test]
public void ShouldAskToRenderTheIndexAspxView()
{
	MockRepository mocks = new MockRepository();
	ProductController controller = mocks.PartialMock<ProductController>();
	using(mocks.Record())
	{
		controller.RenderView("index.aspx"); // <<-- Compiler error here, RenderView is protected!
	}

	using (mocks.Playback())
	{
		controller.Index();
	}
}

Problem, part of the Rhino Mocks design goal was the use of the compiler and tools as verifiers. I explicitly do not want to have strings in my code, and I put them only where I have no other choice. However, since Rhino Mocks by runtime subclassing, there is no issue with reflection calls...

This means that we can get around this limitation by using the following extension method:

public static void RenderView(this Controller self, string action)
{
	typeof(Controller).GetMethod("RenderView").Invoke(self, new object[] { action} );
}

This is it, it will compile and work now.

time to read 3 min | 581 words

Consider this little tidbit:

MockRepository mocks = new MockRepository();
ICustomer customer = mocks.CreateMock<ICustomer>();

using (mocks.Record())
using (mocks.Ordered())
{
	Expect.Call(customer.Id).Return(0);

	customer.IsPreferred = true;
}

using (mocks.Playback())
{
	customer.IsPreferred = true;
}

What would you expect would be the result of this code? Well, it should obviously fail, right? And probably give a message to the effect of unordered method call. Well, it does fail, but it gives the usual message, not talking about ordered method calls at all.

The error message is misleading, what was going on?

I wonder if I am going to bore someone with this description, but what the hell, you can always skip ahead.

Rhino Mocks records all expectations in a recorder. This recorder can be nested. Rhino Mocks has two of those, the Unordered Recorder and the Ordered Recorder. The ability to nest recorders is fairly interesting part of Rhino Mocks, and was a lot of fun to write correctly. It also means that you have a lot of freedom in how you write the tests, because you can specify with great granularity how things are working. (Grouping methods that should run together, for instance.)

But, Rhino Mocks only read from one recorder at a time. Let us talk about a concrete example, shall we? In the above code, here is the recorder structure that we have set up:

image Now, why is this important?

Let us consider how Rhino Mocks will try to resolve a method call.

First, Rhino Mocks will ask the root recorder if it has an expectation that match the method call. The recorder then checks against the recordedActions list.

The recorded actions list contains both normal expectations and nested recorders. When a recorder encounters a nested recorder, it enquire whatever this expectation is valid for the recorder. The nested recorder can say that it isn't, at which point the parent recorder needs to decide what to do. In the unordered recorder case, it will simple move to the next expectation or recorder, but in the ordered recorder case, it will throw an exception because of the unordered method

Here is where it starts to get interesting. Let us look at the playback part of the code above. We call customer.IsPreffered(true);

Rhino Mocks then asks the root recorder whatever this is a valid expectation. The root recorder scans its recorded actions list, which means that it finds the ordered recorder, and then it enquire whatever this is an expected operation.

Well, is customer.set_IsPreffered an expected method call?

No, it is not. The expected (ordered) method call for the ordered recorder is the customer.Id call, so the ordered recorder will answer that this is not an expected call. The root recorder now proceeds to check the rest of the recorded actions list, which is empty, so it finds that we have gotten a completely unknown method, and therefor it throws an exception. But since it is the default, unordered, recorder that throws, we get the unordered version of the exception, not the ordered one, which we have probably been expecting to see.

This is unexpected behavior, but it is precisely how it should behave.

Nevertheless, it violates the rule of least surprise, and this entire post is now mostly irrelevant, because I have just committed a change to Rhino Mocks that ensures that recorders that only contains a single nested recorder are merged with that recorder, which makes it behave in a way that is more in line with the expected behavior.

time to read 2 min | 311 words

It looks like there is some confusion about the way Rhino Mocks 3.3 Expect.Call support for void method works.

Let us examine this support for an instance, shall we? Here is all the code for this feature:

public delegate void Action();

public static IMethodOptions<Action> Call(Action actionToExecute)
{
	if (actionToExecute == null)
		throw new ArgumentNullException("actionToExecute", "The action to execute cannot be null");
	actionToExecute();
	return LastCall.GetOptions<Action>();
}

As you can see, this is simply a method that accept a no args delegate, execute it, and then return the LastCall options. It is syntactic sugar over the usual "call void method and then call LastCall). The important concept here is to realize that we are using the C# * anonymous delegates to get things done.

Let us see how it works?

[Test]
public void InitCustomerRepository_ShouldChangeToCustomerDatabase()
{
	IDbConnection mockConnection = mocks.CreateMock<IDbConnection>();
	Expect.Call(delegate { mockConnection.ChangeDatabase("myCustomer"); });
	
	mocks.ReplayAll();

	RepositoryFactory repositoryFactory = new RepositoryFactory(mockConnection);
	repositoryFactory.InitCustomerRepository("myCustomer");
	
	mocks.VerifyAll();
}

This is how we handle void methods that have parameters, but as it turn out, we can do better for void methods with no parameters:

[Test]
public void StartUnitOfWork_ShouldOpenConnectionAndTransaction()
{
	IDbConnection mockConnection = mocks.CreateMock<IDbConnection>();
	Expect.Call(mockConnection.Open); // void method call
	Expect.Call(mockConnection.BeginTransaction()); // normal Expect call
	
	mocks.ReplayAll();

	RepositoryFactory repositoryFactory = new RepositoryFactory(mockConnection);
	repositoryFactory.StartUnitOfWork("myCustomer");
	
	mocks.VerifyAll();
}

Notice the second line, we are not calling the mockConnection.Open() method, we are using C#'s ability to infer delegates, which means that the code actually looks like:

Expect.Call(new Action(mockConnection.Open));

Which will of course be automatically executed by the Call(Action) method.

I hope that this will make it easier to understand how to use this new feature.

Happy Mocking,

   ~ayende

* Sorry VB guys, this is not a VB feature, but I am not going to rewrite VBC to support this :-) You will be able to take advantage of this in VB9, though, so rejoice.

Rhino Mocks 3.3

time to read 2 min | 235 words

image Well, it has been a couple of months, but we have a new release of Rhino Mocks. I would like to thank Aaron Jensen, Ivan Krivyakov and Mike Winburn for contributing.

Probably the two big new features is the ability to call void methods using Expect.Call and the ability to use remoting proxies to mock classes that inherit from MarshalByRefObject. Rhino Mocks will now choose the appropriate mocking strategy based on the type you want.

Note: you cannot pass constructor arguments or create partial mocks with remoting proxies.

The change log is:

Bug Fixes: 

  • Fixing inconsistency in how Is.Equals handled ICollection instances, now it will compare them by their values, not their Equals() 
  • Fixing NASTY bug where setup result that were defined in a using(mocks.Ordered()) block were not registered properly. 

Improvments:

  • Changing error message to "are you calling a virtual (C#) / Overridable (VB) method?" - make it friendlier to VB guys. 
  • Exception for Record will not trigger a ReplayAll(), which can mask the exception. 
  • Adding a check for running on Mono to avoid calling Marshal.GetExceptionCode in that case.

New features:

  • Adding support for calling void methods using Expect.Call
  • Adding remoting proxies.
  • Made IMethodOptions generic. Allows compile time type safety on Return. 
  • Adding a PublicFieldConstraint

As usual, you can get it here

time to read 1 min | 136 words

One of the things that I dislike about Rhino Mocks is the disconnect between methods that return a value and methods that do not. The first are handled quite naturally using Expect.Call() syntax, but the later have to use the LastCall syntax, which is often a cause of confusion.

There is little to be done there, though, that is a (valid) constraint place there by the compiler, can't do much there, right?

Jim Bolla had a different idea, and had a great suggestion, so now we can write this:

IServer mockServer = mocks.CreateMock<IMock>();
Expect.Call(delegate { mockServer.Start(); }).Throw(new InvalidConigurationException());
// rest of the test

It is also a good way to start preparing Rhino Mocks for C# 3.0.

Many thanks to Jim.

Again, the code is in the repository, and will be released soon.

FUTURE POSTS

  1. A deep dive into RavenDB's AI Agents - 4 days from now
  2. Building an AI Agent using RavenDB - 7 days from now

There are posts all the way to Sep 12, 2025

RECENT SERIES

  1. RavenDB 7.1 (7):
    11 Jul 2025 - The Gen AI release
  2. Production postmorterm (2):
    11 Jun 2025 - The rookie server's untimely promotion
  3. Webinar (7):
    05 Jun 2025 - Think inside the database
  4. Recording (16):
    29 May 2025 - RavenDB's Upcoming Optimizations Deep Dive
  5. RavenDB News (2):
    02 May 2025 - May 2025
View all series

Syndication

Main feed ... ...
Comments feed   ... ...
}