我有一个我想要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及其所有验证等。
答案 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);
这就是Action
,Action<T>
,...,Action<T1, T2, T3, T4>
在框架中定义的全部内容。而已。简单!