2010-03-29 161 views
14

我有一个函数,我想要Moq。问题是它需要5个参数。该框架仅包含Action<T1,T2,T3,T4>和Moq的通用CallBack()仅重载Action和四个通用版本。有没有一个优雅的解决方法呢?Moq有5个参数和访问调用参数的函数

这就是我想做的事:

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 
); 

起订量不允许这样,因为没有通用的用语,使5+参数。我已经使出自己的存根。显然,最好是使用Moq及其所有的验证等。

+0

可能不会帮助你,但在.NET 4.0中动作可能需要多达16个参数! – RichardOD 2010-03-29 20:20:12

+1

即使您使用的是.NET 4.0,Moq在其最新测试版中仍然只支持最多4个参数。要解决这个问题,你必须下载源代码并推出自己的源代码。 – 2010-03-29 20:26:40

+1

您可以使用扩展方法 – Thomas 2011-04-25 20:20:35

回答

3

我知道这可能会破坏你的设计,但有了这么多参数不是更好的传递参数数组吗?

+0

+1,但参数对象可能会更好,如果参数表示不同的概念 – 2010-04-01 08:56:57

+0

正如您在下一个响应中提到的,我需要更改Moq本身,因为它不允许此过载。无论如何,我需要泛型,以便可以访问调用参数。 – beerncircus 2010-04-01 20:37:13

+1

实际上,正如Mark指出的,更好的解决方案是传递一个包含所有需要的参数的对象。当然,这会改变你嘲笑它的方式。 – 2010-04-01 20:52:45

-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>被定义为框架。而已。简单!

+3

您仍然必须修改Moq源代码以在回调中支持四个以上的参数。 – 2010-03-29 20:40:32

+0

@“罗伯特哈维” - 是的,你说得对。我忽略了这一点。也许柯里里可能有用? – Enigmativity 2010-03-29 21:22:17

+0

更改Moq重载以采取5+参数的动作是我看到的唯一解决方案。 “咖喱”是什么意思? – beerncircus 2010-04-01 20:38:44

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 */ }); 
     } 
+0

然后呢?我仍然需要编写自己的方法,这不比修改源代码容易。 – beerncircus 2011-04-26 13:02:47

+0

我更新了我的代码示例以给出一个简单示例。你所做的只是扩展属于moq框架的ICallback接口。您是否熟悉创建扩展方法? – Thomas 2011-04-27 19:12:23

+1

你的扩展方法实际上并没有做任何事情,所以它会如何工作,除了不让编译器抱怨? – 2011-10-19 15:41:55

16

这起订量4.0(4.0.10827),其中发布了4月12日,2011年的最终版本支持如果您使用.NET 4,你就可以嘲笑最多16个参数。

+1

这是迄今为止最好的答案... – 2012-04-21 13:23:29

4

我知道这是一个旧帖子,但我认为这段代码可能会帮助其他人有这个问题与旧版本的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 }); 
    } 
}