Introduction
While writing tests for methods that use .NET Reflection, I found out the Rhino proxy doesn't expose stubbed methods while using reflection. However, Moq, does support such use case.
Background
TDD is very important when it comes to writing libraries or methods that use reflection due to the code being a bit fragile using reflection, given the fact that 90% of the time, you won't get compile time errors. Writing tests that would greatly help spot breaking changes to libraries that would only appear in runtime
Mocked Interface
To demonstrate this difference, I've written a simple test code for a basic interface IAnInterface
having the following definition:
interface IAnInterface
{
bool Get(int Id);
void Process();
}
Writing the Test in RhinoMocks
Writing the following test in RhinoMocks causes a NullReferenceException
at the invocation of method1
.
Using a StrictMock
doesn't help and of course stubbing the GetType()
and GetMethod()
methods are not possible since they're not virtual (yes, I foolishly tried that).
[TestMethod]
public void TestingRhino()
{
var obj = MockRepository.GenerateMock<IAnInterface>();
obj.Stub(x => x.Get(Arg<int>.Is.Anything)).Return(true);
var method1 = obj.GetType().GetMethod(nameof(obj.Get));
var method2 = obj.GetType().GetMethod(nameof(obj.Process));
method1.Invoke(obj, new[] {(object) 99});
method2.Invoke(obj, null);
obj.AssertWasCalled(x => x.Get(99));
obj.AssertWasCalled(x => x.Process());
}
Writing the Test in Moq
Writing the same test in Moq passes the tests and successfully invokes the reflected methods.
[TestMethod]
public void TestingMoq()
{
var mock = new Mock<IAnInterface>();
mock.Setup(x => x.Get(It.IsAny<int>())).Returns(true);
var obj = mock.Object;
var method1 = obj.GetType().GetMethod(nameof(obj.Get));
var method2 = obj.GetType().GetMethod(nameof(obj.Process));
method1.Invoke(obj, new[] {(object) 99});
method2.Invoke(obj, null);
mock.Verify(x => x.Get(99));
mock.Verify(x => x.Process());
}
Points of Interest
While you might prefer a mocking/stubbing/faking framework for one reason or the other, sometimes you're stuck at things that simply work in one framework vs the other.
I didn't try other frameworks other than the Moq and Rhino. Please state in the comments if it works on your favourite mocking framework.