Moq функция с 5+ параметрами и доступом к аргументам вызова - PullRequest
14 голосов
/ 30 марта 2010

У меня есть функция, которую я хочу Moq. Проблема в том, что он принимает 5 параметров. Каркас содержит только Action<T1,T2,T3,T4>, а универсальный CallBack() только для Moq перегружает Action и четыре универсальные версии. Есть ли элегантный обходной путь для этого?

Вот что я хочу сделать:

public class Filter : IFilter  
{  
    public int Filter(int i1, int i2, int i3, int i4, int i5){return 0;}  
}

//Moq code:
var mocker = new Mock<IFilter>();  
mocker.Setup(x => x.Filter(  
    It.IsAny<int>(),  
    It.IsAny<int>(),  
    It.IsAny<int>(),  
    It.IsAny<int>(),  
    It.IsAny<int>(),  
    It.IsAny<int>())  
.Callback
(  
    (int i1, int i2, int i3, int i4, int i5) => i1 * 2  
);  

Moq не позволяет этого, потому что нет общего действия, которое принимает 5+ параметров. Я прибег к изготовлению моей собственной заглушки. Очевидно, что было бы лучше использовать Moq со всеми его проверками и т. Д.

Ответы [ 5 ]

16 голосов
/ 19 октября 2011

Это поддерживается в финальной версии Moq 4.0 (4.0.10827), выпущенной 12 апреля 2011 года. Если вы используете .NET 4, вы сможете смоделировать до 16 параметров. 1001 *

5 голосов
/ 08 мая 2013

Я знаю, что это старый пост, но я подумал, что этот код может помочь другим, имеющим эту проблему с более старой версией Moq. Вот пример с 5 и 6 аргументами, и он может быть расширен для поддержки любого числа.

Я проверил это с версией 3.1.0.0, но она должна работать и с другими версиями.

Секрет в использовании отражения для доступа к защищенному методу SetCallbackWithArguments в базовом классе ...

Надеюсь, это кому-нибудь пригодится!

public delegate void Action<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
public delegate void Action<T1, T2, T3, T4, T5, T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);

public static class MoqExtensions
{
    public static ICallbackResult Callback<T1, T2, T3, T4, T5>(this ICallback call, Action<T1, T2, T3, T4, T5> callback)
    {
        call.SetCallbackWithArguments(callback);
        return (ICallbackResult)call;
    }

    public static ICallbackResult Callback<T1, T2, T3, T4, T5, T6>(this ICallback call, Action<T1, T2, T3, T4, T5, T6> callback)
    {
        call.SetCallbackWithArguments(callback);
        return (ICallbackResult)call;
    }

    public static void SetCallbackWithArguments(this ICallback call, Delegate callback)
    {
        MethodInfo methodInfo = call.GetType().GetMethod("SetCallbackWithArguments", BindingFlags.NonPublic | BindingFlags.Instance);
        methodInfo.Invoke(call, new object[] { callback });
    }
}
3 голосов
/ 26 апреля 2011

Используйте метод расширения для расширения среды moq, если вы не хотите изменять источник.

//Extension Method

    public static class MoqExtensions
    {
        public static void Callback<T1, T2, T3, T4, T5>(this ICallback iCallBack, Action<T1, T2, T3, T4, T5> action)
        {
        }
    }

//Your class and interface

        public interface IMyClass
        {
            void Method(string arg1, string arg2, string arg3, string arg4, string arg5);
        }

        public class MyClass : IMyClass
        {
            public void Method(string arg1, string arg2, string arg3, string arg4, string arg5)
            {
                //Do something
            }
        }

//Your test

        [TestMethod]
        public void ExampleTest()
        {
            Mock<IMyClass> mockMyClass = new Mock<IMyClass>();
            mockMyClass.Setup(s => s.Method(It.IsAny<string>(),
                                            It.IsAny<string>(),
                                            It.IsAny<string>(),
                                            It.IsAny<string>(),
                                            It.IsAny<string>()))
                .Callback<string, string, string, string, string>((string arg1, string arg2, string arg3, string arg4, string arg5) 
                    => { /* Run your mock here */ });
        }
3 голосов
/ 30 марта 2010

Я знаю, что это, вероятно, нарушает ваш дизайн, но с таким количеством параметров не лучше ли передать массив параметров?

0 голосов
/ 30 марта 2010

Это на самом деле довольно просто. Просто определите свой Action<T1, T2, T3, T4, T5>, и вы готовы.

public delegate void Action<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5);

Это все, что Action, Action<T>, ..., Action<T1, T2, T3, T4> определены как в рамках. Ничего более. Простой!

...