I’ve encountered a problem on how Rhino.Mocks handles unexpected
method calls on mocks in certain situations where there is a mixture
of generic and non-generic methods called.

Here’s an example piece of code that reproduces the problem:

        public interface IFoo
        {
            void GenericMethod<T>();
            void NonGenericMethod();
        }

        public static void Main()
        {
            MockRepository mockRepos = new MockRepository();
            IFoo mock = mockRepos.StrictMock<IFoo>();

            mock.NonGenericMethod();

            mockRepos.ReplayAll();

            mock.NonGenericMethod();
            mock.GenericMethod<object>(); // Should throw
ExpectationViolationException,
                                                            // but
throws InvalidOperationException.
        }

There’s no expectation for the call to GenericMethod(), so I would
expect an ExpectationViolationException, but instead an
InvalidOperationException is thown with the following stack trace:

   at System.Reflection.RuntimeMethodInfo.GetGenericMethodDefinition()
   at Rhino.Mocks.MethodRecorders.UnorderedMethodRecorder.MethodsEquals
(MethodInfo method, ProxyMethodExpectationTriplet triplet)
   at
Rhino.Mocks.MethodRecorders.UnorderedMethodRecorder.GetAllExpectationsForProxyAndMethod
(Object proxy, MethodInfo method)
   at
Rhino.Mocks.MethodRecorders.UnorderedMethodRecorder.CalcExpectedAndActual.Calculate
(Object proxy, MethodInfo method, Object[] args)
   at
Rhino.Mocks.MethodRecorders.UnorderedMethodRecorder.CalcExpectedAndActual..ctor
(UnorderedMethodRecorder parent, Object proxy, MethodInfo method,
Object[] args)
   at
Rhino.Mocks.MethodRecorders.UnorderedMethodRecorder.UnexpectedMethodCall
(IInvocation invocation, Object proxy, MethodInfo method, Object[]
args)
   at
Rhino.Mocks.MethodRecorders.UnorderedMethodRecorder.DoGetRecordedExpectation
(IInvocation invocation, Object proxy, MethodInfo method, Object[]
args)
   at
Rhino.Mocks.MethodRecorders.MethodRecorderBase.GetRecordedExpectation
(IInvocation invocation, Object proxy, MethodInfo method, Object[]
args)
   at Rhino.Mocks.Impl.ReplayMockState.DoMethodCall(IInvocation
invocation, MethodInfo method, Object[] args)
   at Rhino.Mocks.Impl.ReplayMockState.MethodCall(IInvocation
invocation, MethodInfo method, Object[] args)
   at Rhino.Mocks.MockRepository.MethodCall(IInvocation invocation,
Object proxy, MethodInfo method, Object[] args)
   at Rhino.Mocks.Impl.RhinoInterceptor.Intercept(IInvocation
invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at IFooProxyf637724feb334bf5bc3b967248b5653b.GenericMethod[T]()

I haven’t seen this exception when tests pass, it has only happened
when an expectation violation failure is produced. It's still
frustrating not to get a clear expectation violation message in this
case. All I can deduce from this failure is that something unexpected
was probably called.

Looking at the stack trace and source code (from github), I suspect
that UnorderedMethodRecorder.MethodsEquals() might be defective:

    private static bool MethodsEquals(MethodInfo method,
ProxyMethodExpectationTriplet triplet)
    {
        if(method.IsGenericMethod==false)
             return triplet.Method == method;
        return triplet.Method.GetGenericMethodDefinition() ==
method.GetGenericMethodDefinition();
    }

What if method.IsGenericMethod==true, but
triplet.Method.IsGenericMethod==false? In this case
triplet.Method.GetGenericMethodDefinition() is called and that throws
InvalidOperationException because the method is not generic.

Does anyone agree that this is a defect?

This applies to versions 3.6 and 3.5 at least.

Thanks.

-Juhani
-- 
You received this message because you are subscribed to the Google Groups 
"Rhino.Mocks" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rhinomocks?hl=en.


Reply via email to