Moq是一个具有5个以上参数和访问调用参数的函数

时间:2010-03-29 20:13:31

标签: c# moq delegates action

我有一个我想要Moq的功能。问题是需要5个参数。该框架仅包含Action<T1,T2,T3,T4>,而Moq的通用CallBack()仅重载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不允许这样做,因为没有通用的Action需要5个参数。我已经使用了自己的存根。显然,最好使用Moq及其所有验证等。

6 个答案:

答案 0 :(得分:16)

2011年4月12日发布的Moq 4.0(4.0.10827)的最终版本支持此功能。如果您使用的是.NET 4,则最多可以模拟16个参数。< / p>

答案 1 :(得分:5)

我知道这是一篇旧帖子,但我认为这段代码可以帮助其他人在旧版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 });
    }
}

答案 2 :(得分:3)

我知道这可能会破坏你的设计,但是传递一个param数组并不是更好的参数吗?

答案 3 :(得分:3)

如果您不想修改源代码,请使用扩展方法扩展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 */ });
        }

答案 4 :(得分:0)

delegate void SubmitCallback(Bar bar1,Bar bar2,Bar bar3,Bar bar4,Bar bar5);

mock.Setup(foo => foo.Submit(It.IsAny<Bar>(),It.IsAny<Bar>(),It.IsAny<Bar>(),It.IsAny<Bar>(),It.IsAny<Bar>()))
    .Callback(new SubmitCallback((Bar bar1,Bar bar2,Bar bar3,Bar bar4,Bar bar5) => Console.WriteLine("Submitting a Bar!")));

您可以通过委托使用超过 16 个参数。 :)

答案 5 :(得分:-1)

这实际上非常简单。只需定义自己的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);

这就是ActionAction<T>,...,Action<T1, T2, T3, T4>在框架中定义的全部内容。而已。简单!