Ayende @ Wiki

Some stumbling blocks you might come across while using Rhino.Mocks:


Generic Method Matching

At first glance, you might expect this test to pass:

using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Rhino.Mocks;

namespace RhinoMocksIssue { TestFixture public class GenericMethodTest { Test public void should_return_stubbed_value_from_generic_method() { var club = new Club(); var manager = new Manager();

var managerFinder = MockRepository.GenerateMock(); managerFinder.Stub(t => t.For(club)).Return(manager);

var underTest = new UnderTest(managerFinder);

Assert.That(underTest.GetManagerFor(club), Is.EqualTo(manager)); } }

public class UnderTest { private readonly ManagerFinder managerFinder;

public Manager GetManagerFor(SportingGroup sportingGroup) { return managerFinder.For(sportingGroup); }

public UnderTest(ManagerFinder managerFinder) { this.managerFinder = managerFinder; } }

public class Manager { }

public interface ManagerFinder { Manager For<ENTITY>(ENTITY entity); }

public class Club : SportingGroup { }

public interface SportingGroup { } }

Unfortunately, it doesn't. underTest.GetManagerFor(club) returns null. Even though you passed the same object (var club = new Club();) to the mock object when you set up the stub and when you used it from your class under test.

This is because the CLR treats generic methods with different type parameters as different methods. You have stubbed a call to For<Club>(), then called For<SportingGroup>(). Again, these are different methods in the CLR. The binding of the method call in GetManagerFor() is performed at compile time, so it is bound to For<SportingGroup>().

The solution is to explicitly specify the type parameter of your generic call:
        managerFinder.Stub(t => t.For<SportingGroup>(club)).Return(manager);

Up: Rhino Mocks Documentation

ScrewTurn Wiki version 2.0 Beta. Some of the icons created by FamFamFam.