2011-03-15 39 views
36

我有一個接口嘲諷泛型方法調用任何給定的類型參數

public interface IDataProvider 
{ 
    T GetDataDocument<T>(Guid document) where T:class, new() 
} 

我想嘲笑它在某種程度上,這將只返回給定類型的新實例,無論確切類型,是這樣的:

myMock.Setup(m => m.GetDataDocument<It.IsAny<Type>()>(It.IsAny<Guid>())) 
.Returns(() => new T()); 

(這並不當然的工作,因爲我不能隨便給任何類型的參數,起訂量,我不知道哪種類型必須返回

所有。關於這一點的想法?

回答

25

而不是使用模擬,也許你的情況會更好地使用Stub

public class StubDataProvider : IDataProvider 
{ 
    public T GetDataDocument<T>(Guid document) where T : class, new() 
    { 
     return new T(); 
    } 
} 

如果你真的需要一個模擬(這樣你就可以驗證GetDataDocument叫)。與其試圖與Mocking框架搏鬥,有時候更容易創建一個Mock類。

public class MockDataProvider : IDataProvider 
{ 
    private readonly Action _action; 

    public MockDataProvider(Action action) 
    { 
     _action = action; 
    } 

    public T GetDataDocument<T>(Guid document) where T : class, new() 
    { 
     _action(); 
     return new T(); 
    } 
} 

,比你的測試:

bool wasCalled = false; 
IDataProvider dataProvider = new MockDataProvider(() => { wasCalled = true; }); 
var aTable = dataProvider.GetDataDocument<ATable>(new Guid()); 
Debug.Assert(wasCalled); 
+2

好解決方案,儘管我希望看到一些模擬/存根框架可以自動執行此操作:)我會盡量等待一會,也許另一個答案會提示auotomatic解決方案。 – Hassan 2011-03-15 12:29:43

11

對於你將要使用這個模擬的特定測試,你可能知道T會是什麼,對吧?

只是簡單地設置模擬爲:

myMock.Setup(m => m.GetDataDocument<MyDataClass>()>(It.IsAny<Guid>())) 
    .Returns(() => new MyDataClass()); 

它並不推薦反正重用嘲笑,所以,儘管設置嘲笑手頭的實際測試。

+19

沒有,整點是,我不知道確切的類型,我知道這幾種類型將被使用,但我懶得寫不同的設置條款對他們所有:) – Hassan 2011-03-15 12:26:50

4

我有一個類似的問題,我選擇了對在這種情況下使用存根,因爲我不希望增加的接口被測試需要立即改變到測試代碼。即增加一種新方法不應該破壞我現有的測試。

爲了得到模擬工作,我在運行時添加了給定程序集中的所有公共類型。

//This is fairly expensive so cache the types 
static DummyRepository() 
{ 
    foreach(var type in typeof(SomeTypeInAssemblyWithModelObjects).Assembly.GetTypes()) 
    { 
     if(!type.IsClass | type.IsAbstract || !type.IsPublic || type.IsGenericTypeDefinition) 
     { 
      continue; 
     } 

     g_types.Add(type); 
    } 
} 

public DummyRepository() 
{ 
    MockRepository = new Mock<ISomeRepository>(); 

    var setupLoadBy = GetType().GetMethod("SetupLoadBy", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod); 

    foreach(var type in g_types) 
    { 
     var loadMethod = setupLoadBy.MakeGenericMethod(type); 
     loadMethod.Invoke(this, null); 
    } 
} 

private void SetupLoadBy<T>() 
{ 
    MockRepository.Setup(u => u.Load<T>(It.IsAny<long>())).Returns<long>(LoadById<T>); 
} 

public T LoadById<T>(long id) 
{ 
} 
相關問題