Search code examples
c#.netc#-4.0microsoft-fakes

How to mock a generic method with delegate in it using Fakes


I am having a method as below which I want to mock using Fakes. Any help in this regard is really appreciated?

IEnumerable<T> ExecuteReader<T>(
    string commandText, 
    Func<IDataRecord, T> returnFunc, 
    int timeOut = 30);

Solution

  • Assuming you've generated the fakes assembly for the interface/class in question then it depends if you're using an interface (or virtual method) to define the method or only a class. If an interface or virtual method, you can use a stub like

        [TestMethod]
        public void StubFuncTest()
        {
            StubITestReader stubClass = new StubITestReader();
            stubClass.ExecuteReaderOf1StringFuncOfIDataRecordM0Int32<int>((str, func, timeout) =>
            {
                int[] retVal = {12, 25, 15};
                return retVal;
            });
    
            ITestReader reader = stubClass;
            IEnumerable<int> curInt = reader.ExecuteReader<int>("testText", TestFunc);
            foreach (var i in curInt)
            {
                Console.WriteLine(i);
            }
        }
    

    or if just a standard method, you'll need to use a shim (I would advise to use the first option)

        [TestMethod]
        public void ShimFuncTest()
        {
            TestUnitTestClass tutClass = new TestUnitTestClass();
            using (ShimsContext.Create())
            {
                ShimTestUnitTestClass shimClass = new ShimTestUnitTestClass(tutClass);
                shimClass.ExecuteReaderOf1StringFuncOfIDataRecordM0Int32<int>((str, func, timeout) =>
                {
                    int[] retVal = {12, 25, 15};
                    return retVal;
                });
    
                IEnumerable<int> curInt = tutClass.ExecuteReader<int>("testText", TestFunc);
                foreach (var i in curInt)
                {
                    Console.WriteLine(i);                    
                }
            }
        }
    

    Adding response to comment
    It's a bit easier for normal methods. Using the stub, it would be something like

        [TestMethod]
        public void StubRegFuncTest()
        {
            StubITestReader stubClass = new StubITestReader();
            stubClass.ExecuteNonQueryStringInt32 = (str, timeout) => timeout * 2;
    
            ITestReader reader = stubClass;
            int curInt = reader.ExecuteNonQuery("testText");
            Console.WriteLine(curInt);
            curInt = reader.ExecuteNonQuery("testText", 10);
            Console.WriteLine(curInt);
        }
    

    The not-so-obvious difference is the generic method is enclosed in parenthesis while the normal method is just lambda expression and code block.