Ayende @ Rahien

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


+972 52-548-6969

, @ Q c

Posts: 6,128 | Comments: 45,549

filter by tags archive

Using Expect.Call( void method )

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");
	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?

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

	RepositoryFactory repositoryFactory = new RepositoryFactory(mockConnection);

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:

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

	RepositoryFactory repositoryFactory = new RepositoryFactory(mockConnection);

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,


* 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.


Julien Rivi&#232;re

It made me feel I totally misunderstood the Expect.On method. In your example you passed a string to the method of the mocked object. If I have an argument other than basic type, and declare it in the delegate, It doesn't compile.

Where can I have documentation of Rhino Mocks?

public abstract class AddInBase


    public abstract void Load(IContainer container);

    public abstract void Unload();


AddIn1 is a basic implementation used for testing.

Now here is the test:

MockRepository mocks = new MockRepository();

AddInBase addIn = mocks.CreateMock();

Expect.Call( delegate(IContainer container) { addIn.Load(container); } ); //doesnt compile

Expect.Call(addIn.Unload); //compile

//... (replay, test, verify)

Thx in advance.

Ayende Rahien

Expect.Call( delegate { addIn.Load(container); } ); //compile

Julien Rivi&#232;re

Thx for the quick replay.

I had to change things in order to make it work (ie by declaring a mocked IContainer). However, I'm not sure wether I did it like it's supposed to be or not.

Keep up the good work, Rhino made me use mocks again (NMock implied too much work), even if I feel like not understand it completely.

Is there any place where I could get further information on Expect, MockRepository or RepositoryFactory usage ?

PS I'm sorry If my english is not good enough or If my questions seem stupid.

Ayende Rahien


And the rhino mocks mailing list.

Fabian Schmied

Hm, I'm sure you have already thought about that, but what's the reason you don't just provide overloads for different void method delegates with a different number of arguments?

Like this:

delegate void Proc();

delegate void Proc(A1 a1);

delegate void Proc<A1, A2>(A1 a1, A2 a2);

delegate void Proc<A1, A2, A3>(A1 a1, A2 a2, A3 a3);


public static IMethodOptions Call(Proc actionToExecute)




public static IMethodOptions<Proc> Call(Proc actionToExecute)




public static IMethodOptions<Proc<A1, A2>> Call<A1, A2>(Proc<A1, A2> actionToExecute)





While cumbersome to write for you, it would enable people to write:

Expect.LastCall (myObject.VoidMethod)

Expect.LastCall (myObject.VoidMethod(1))

Expect.LastCall (myObject.VoidMethod(1, 2))

and so on without needing to write anonymous delegates. Making the syntax the same for void and non-void methods.


Ayende Rahien

Because it would have to be written as:

Expect.LastCall (myObject.VoidMethod)

Expect.LastCall (myObject.VoidMethod, 1)

Expect.LastCall (myObject.VoidMethod,1,2)

Certainly possible, but is it easy to read?

Fabian Schmied

You're right, I missed that. Not easier to read than the delegate keyword.


Fabian Schmied

Of course, you could change the whole syntax for both void methods and non-void methods to use delegates:

Expect.Call (myObject.MyMethod).With (arg1, arg2)

(Where myObject.MyMethod is automatically converted to either a Proc<...> or a Func<...>.)

That way, the syntax would really be the same for void and non-void methods. Using overloading, the "With" method could be strongly typed (i.e. provide exactly the same signature as MyMethod), the Constraints method could be made to know how many parameter constraints to accept, and the Returns method could be made available only for non-void methods.

But at the same time, it would be a very breaking change, and you would lose that "like a method call" feeling :)


Ayende Rahien


The C# compiler isn't that smart about inferencing

Fabian Schmied

Damn, you are right, the C# compiler cannot infer the generic arguments from what I wrote above! Quite lame, actually.

Jeff Litster

When we use Expect.Call() with either void or non-void method calls in 3.3, we lose the intellisense we used to have.

We only get intellisense when we use:

Expect.Call() which only works for non-void methods.

Do we know why this occurs and has anyone else seen this behavior?

Ayende Rahien

I have not run into this behavior, can you explain a bit furhter, do you have any addons that affect intelklisense?

Jeff Litster

We have the JetBrains Unit Test Runner plug-in. That plug-in shows signs that it may contain some of the ReSharper code in it as well (we're using the standalone test runner.) I haven't confirmed that to be true, but we'll see random JetBrains exceptions be thrown at times where intellisense events occur that ReSharper would normally handle.

That said, it was fair to assume that it might be interfering. However, I uninstalled the JetBrains Add-In and still see the same behavior when using the 3.3 Rhino.Mocks dll. When we switch back to 3.2 we get the intellisense back.

I will seek a machine that has never had the JetBrains add-in to see if we get the same behavior.

David Mohundro

Jeff, I'm having similar behavior if I'm understanding what you're saying correctly. Here's what it is doing for me:

Given the following:

interface IFoo


string GetValue();


void Testing()


MockRepository mocks = new MockRepository();

IFoo foo = mocks.CreateMock();



When I type the "Expect.Call(foo.GetValue())." I don't get the intellisense popping up to show me "Return." If I explicitly type "Expect.Call(foo.GetValue()).", I get the intellisense.

Does that make sense? Is that by design now?

Jeff Litster

David, that is identical behavior to what we're experiencing. It happens on all machines we've tried it on.

David Mohundro

Looking through the Expect.cs code, I'm guessing that VS Intellisense isn't smart enough to figure out that there is a difference between IMethodOptions Call(T ignored) and IMethodOptions Call(Action actionToExecute).

Ayende Rahien


sorry for taking so long to respond, I have not been able to reproduce this.

Peter Stromquist

Yep, getting the same behavior here now that we've upgraded to 3.3. Per the last comment, it almost seems like a bug (or feature) of the IDE. Given that, it may be a difficult one to solve.

Ayende, any updates on this?

Wojtek Kucia

So I can also confirm the same behavior

After upgrading to Rhino 3.3

In my canse GhostDoc is on the AddOn list, but I don't think that this is the case.

Jeff Litster

I spoke with Ayende about the theory that there might be a Visual Studio add-on that would be affecting the intellisense.

I asked Ayende if he had one that would affect it and he told me JetBrains ReSharper.

I downloaded and installed the evaluation version and I now have intellisense for both the Generic and non-Generic versions of Expect.Call.

ReSharper is smart enough to catch and handle the intellisense... it appears Microsoft's default intellisense is not.

While this only provides a solution of: "Get ReSharper", it at least we know how to reproduce the problem.

However, I don't know that this is a Rhino Mocks' responsibility to fix... seems like we need to be getting after Microsoft.

If Ayende feels compelled to check this out, I've confirmed that disabling the Re-Sharper plug-in will make the behavior reproducable (you don't have to uninstall it.)

If you want a quick fix for now, check out JetBrains ReSharper.

Comment preview

Comments have been closed on this topic.


  1. The worker pattern - 2 days from now

There are posts all the way to May 30, 2016


  1. The design of RavenDB 4.0 (14):
    26 May 2016 - The client side
  2. RavenDB 3.5 whirl wind tour (14):
    25 May 2016 - Got anything to declare, ya smuggler?
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats