2

I have following code.

public class MyClass
{
    protected virtual IEnumerable<TResult> MyMethod<TResult>(Func<IDataReader, IEnumerable<TResult>> arg)
    {
       ....
    }
} 

How can I Setup a Mock method for this?

I tried following but getting an error.

using Moq;
using Moq.Protected;
namespace Foo
{
    [TestClass]
    public class TestClass
    {
        Mock<MyClass> m_mockObject = null;
        [TestMethod]
        public void MyTest()
        {
            m_mockObject = new Mock<MyClass>();
            AddMethod<Func<IDataReader, IEnumerable<SomeOtherClass>>, IEnumerable<SomeOtherClass>>(this.MyMethod);

        }

        private void AddMethod<TIn, TResult>(Func<TIn, TResult> method)
        {
             m_mockObject.Protected().Setup<TResult>(method.Method.Name, ItExpr.IsAny<TIn>())
                                                    .Returns(method); /* THIS LINE IS THROWING THE EXCEPTION */
        }

        public IEnumerable<TResult> MyMethod<TResult>(Func<IDataReader, IEnumerable<TResult>> arg)
        {
            ....
        }
    }
}

Once I run the code I get following error on the call to Setup function.

> System.ArgumentException was unhandled by user code
  HResult=-2147024809
  Message=Expression of type 'System.Object' cannot be used for return type 'System.Collections.Generic.IEnumerable`1[SomeOtherClass]'
  Source=System.Core
  StackTrace:
       at System.Linq.Expressions.Expression.ValidateLambdaArgs(Type delegateType, Expression& body, ReadOnlyCollection`1 parameters)
       at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, String name, Boolean tailCall, IEnumerable`1 parameters)
       at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, Boolean tailCall, IEnumerable`1 parameters)
       at System.Linq.Expressions.Expression.Lambda[TDelegate](Expression body, ParameterExpression[] parameters)
       at Moq.Protected.ProtectedMock`1.Setup[TResult](String methodOrPropertyName, Object[] args)
       ....
       .....
  InnerException: 
Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
Code Ninja
  • 93
  • 1
  • 8

3 Answers3

4

not sure why you are returning a method.. but could you try changing it to:

m_mockObject.Protected().Setup<IEnumerable<TResult>>(method.Method.Name, ItExpr.IsAny<TIn>()).Returns(new List<TResult>());

See if that works..

  • 2
    I believe I found the root cause of the issue, Mock.Protected is not doing the right thing when using reflection for Generic type methods, the following link provides more details about the root cause of they bug they have http://stackoverflow.com/questions/269578/get-a-generic-method-without-using-getmethods Thanks a lot for your help. – Code Ninja Jul 17 '14 at 01:11
  • Interestingly enough, using `ItExpr.IsAny<...>()` instead of `It.IsAny<...>()` fixed my problem, and I'm not sure why `It` doesn't work in this scenario. – Michael Plautz Feb 07 '18 at 17:45
1

myMethod1 returns an IEnumerable<TResult>, not a delegate like I think you are expecting.

BanksySan
  • 27,362
  • 33
  • 117
  • 216
0

I believe I found the root cause of the issue, Mock.Protected is not doing the right thing when using reflection for Generic type methods, the following link provides more details about the root cause of they bug they have Get a generic method without using GetMethods

Thanks a lot for your help.

Community
  • 1
  • 1
Code Ninja
  • 93
  • 1
  • 8