Welcome to MSDN Blogs Sign in | Join | Help

Mocking Generic Methods With NMock2

Recently I was asked how to mock a generic method, now that NMock2 supports generics. Here's how:

Suppose you have this interface:

public interface IMyInterface
{
    T DoStuff<T>();

And this class using IMyInterface:

public class MyClass
{
    private IMyInterface mi_;
 
    public MyClass(IMyInterface mi)
    {
        this.mi_ = mi;
    }
 
    public string DoSomething()
    {
        return this.mi_.DoStuff<string>();
    }
}

Now, you want to write a unit test where you validate that if DoStuff<string> returns Ploeh, MyClass.DoSomething will also return Ploeh. On the version of NMock2 currently installed on my laptop, this is easily done like this:

[TestMethod]
public void ValidateDoSomething()
{
    Mockery mocks = new Mockery();
    IMyInterface mi = mocks.NewMock<IMyInterface>();
    Expect.Once.On(mi).Method("DoStuff").Will(Return.Value("Ploeh"));
 
    MyClass mc = new MyClass(mi);
    string result = mc.DoSomething();
 
    Assert.AreEqual<string>("Ploeh", result);
    mocks.VerifyAllExpectationsHaveBeenMet();
}

The only thing which is slightly surprising here is that the method name expected is DoStuff, without any indications of generics - I first expected that I should have indicated the method name as DoStuff`1, but apparently, NMock2 doesn't care whether you are expecting a generic or non-generic version of a method (if DoStuff had had a non-generic overload).

Note that this is based on a release candidate of NMock2, so there's no guarantee that this will work exactly identical in the final release.

Published Sunday, October 29, 2006 9:21 PM by ploeh
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: Mocking Generic Methods With NMock2

Saturday, November 18, 2006 4:00 PM by Martin Jul

Mark, do yourself the favour of checking out the brilliant Rhino Mocks framework at www.ayende.com/projects/rhino-mocks.aspx

You will be please that it uses a "recording" metaphor for setting up the expectations. This means that expectatations are set up using actual calls to methods the mock, not through the name of the method as a String as in NMock.

This benefit of this approach is that your refactoring tools can refactor you unit tests, too, when you rename a method.

Also, we've seen in a project earlier this year that Rhino Mocks does not claim as much memory as NMock - I think it emits fewer classes to linger in-memory until the AppDomain is shut down. If you have a test suite with thousands of tests and a few gigabytes too little memory this really helps speeds up the test suite execution.

# re: Mocking Generic Methods With NMock2

Saturday, November 18, 2006 4:35 PM by ploeh

Hi Martin

Thank you for the tip! I've been keeping an eye on Rhino Mocks for some time, and I really like that it's not string-based, but type safe. On the other hand, according to the documentation, it currently doesn't support mocking generic methods, and this has scared me away from it so far, since I tend to use these from time to time :)

# re: Mocking Generic Methods With NMock2

Monday, January 15, 2007 5:41 AM by Gary Murchison

Hi Mark,

hope you are still reading comments on this post!

I've got a (very basic) generic service registry IServiceRegistry which has the generic method GetServiceFor<T> .  However when I am mocking this I need to tell NMock what the type T is (so tha I can tell NMock to serve up different mocked services depending on what T is)

Any ideas on how this is done?

# re: Mocking Generic Methods With NMock2

Monday, January 15, 2007 5:55 AM by ploeh

Hi Gary

Thank you for your comment. As far as I can tell, your scenario looks like it's equivalent with the post's sample code. It sounds to me that your IServiceRegistry corresponds to IMyInterface in the sample, and that your GetServiceFor<T> corresponds to DoStuff<T>, or am I missing something?

Since you are asking, I guess I am, but if that is the case, I'll need a bit more information on what it is that you are trying to do.

# re: Mocking Generic Methods With NMock2

Monday, January 15, 2007 6:02 AM by Gary Murchison

wow, prompt response (thanks!)

public interface IServiceRegistry

{

       T GetServiceFor<T>();

}

[Test]

       public void ThisDoesNotwork()

       {

           Mockery mockery = new Mockery();

           IServiceRegistry mockServices = mockery.NewMock<IServiceRegistry>();

           IPolicyConfiguration mockPolicyConfig = mockery.NewMock<IPolicyConfiguration>();

           IChargingConfiguration mockChargingConfig = mockery.NewMock<IChargingConfiguration>();

           // The problem!!!

           Stub.On(mockServices).Method("GetServiceFor").Will(Return.Value(mockChargingConfig));

           Stub.On(mockServices).Method("GetServiceFor").Will(Return.Value(mockPolicyConfig));

           // Do test

           mockery.VerifyAllExpectationsHaveBeenMet();

       }

# re: Mocking Generic Methods With NMock2

Monday, January 15, 2007 6:45 AM by ploeh

Hi Gary

Thank you for sharing your code. I just recently rebuilt my machine and haven't gotten around to put NMock2 on it yet, so I can't verify the following myself, but here's a theory:

Now, you don't write what symptoms you are suffering, but if all method calls to GetServiceFor returns only the mockPolicyConfig object, I think the key to your problem lies in your usage of Stub instead of Expect.

As far as I understand the implementation of Stub, it always returns the same value, no matter how many times it is called. As such, unlike Expect, there's no expectation stack, so your second Stub definition (the second line of code where you use Stub) effectively overwrites the first.

If I'm right so far, replacing your usage of Stub with calls to Expect may solve your problem. If you even need to ensure a correct order (as I suppose you do in this case) you can constrain the order (see e.g. http://nmock.org/cheatsheet.html).

Please let me know if this solves your problem.

# re: Mocking Generic Methods With NMock2

Monday, January 15, 2007 7:23 AM by Gary Murchison

Thanks!

Expect.Once does the trick!

Thanks again,

Gary.

# re: Mocking Generic Methods With NMock2

Monday, January 15, 2007 8:38 AM by ploeh

Hi Gary

Thanks for letting me know. I'm happy I could be of assistance :)

# re: Mocking Generic Methods With NMock2

Wednesday, October 10, 2007 1:24 AM by eric han

this is easy and useful sample.

many thanks about that.

# re: Mocking Generic Methods With NMock2

Saturday, May 31, 2008 7:20 AM by Urs Enzler - NMock2 dev team

In V1.0 on https://sourceforge.net/projects/nmock2/ of NMock2  you can specify type parameters on methods in expectations:

Expect.Once.On(mockServices).Method("GetServiceFor", typeof(IPolicyConfiguration)).Will(Return.Value(mockery.NewMock<IPolicyConfiguration>()));

Therefore no ordered expectations are needed anymore.

# re: Mocking Generic Methods With NMock2

Friday, October 03, 2008 5:31 AM by AJ

My NMock tests looks as follows;

public interface IMyInterface

       {

           string DoStuff<T>();

       }

       [Test]

       public void ValidateDoSomething()

       {

           Mockery mocks = new Mockery();

           IMyInterface mi = mocks.NewMock<IMyInterface>();

           Expect.Once.On(mi).Method("DoStuff").Will(Return.Value("Ploeh"));

           mocks.VerifyAllExpectationsHaveBeenMet();

       }

Here when i try to create a NMock object i am getting a TypeOverloading exception. i.e. when executing line "IMyInterface mi = mocks.NewMock<IMyInterface>();" i am getting following;

System.TypeLoadException: Signature of the body and declaration in a method implementation do not match.  Type: 'MockObjectType1'.  Assembly: 'MockObjects, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

I am grateful if you can explain the cause for this.

Thank You

AJ

# re: Mocking Generic Methods With NMock2

Monday, October 06, 2008 4:37 AM by ploeh

Hi AJ

It's a long time ago I used NMock, and I've never really used NMock2, so I've never seen this particular error before.

Do you get the same error if you reproduce my code completely?

# re: Mocking Generic Methods With NMock2

Thursday, January 29, 2009 8:58 AM by Vladlen Fomushkin

Got interface with generic method similar to described in this blog and tried NMock 2.0 Release Candidate 1 and NMock 2.0 Release Candidate 2. NMock 2.0 Release Candidate 2 gets TypeLoadException. NMock 2.0 Release Candidate 1 works.

# re: Mocking Generic Methods With NMock2

Thursday, January 29, 2009 9:23 AM by ploeh

Hi Vladlen

Thank you for your comment. May I suggest that you log this as a bug against NMock 2.0 Release Candidate 2, then?

Otherwise, you could always just decide to use Rhino Mocks instead ;)

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker