2010-03-29 40 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 }); 
    } 
}