2013-04-09 56 views
3

我有一個依賴,我想嘲笑。我可以使用Moq爲字段設置值嗎?

public abstract class MyDependency 
{ 
    protected Dictionary<string, object> _outputs = new Dictionary<string, object>(); 
    public Dictionary<string, object> Outputs 
    { 
     get 
     { 
      return _outputs; 
     } 
    } 
} 

我需要的公共財產Outputs爲我的單元測試的目的返回一個已知值。我知道我們不能嘲笑字段或非虛擬成員。所以,我可以去創建自己的嘲笑MyDependency,設置支持字段_outputs

public class MockMyDependency : MyDependency 
{ 
    public MockMyDependency() 
    { 
     _outputs = new Dictionary<string, object> 
     { 
      { "key", "value" } 
     }; 
    } 
} 

然而,就是有可能使用起訂量來做到這一點沒有明確地創造我自己的派生模擬類?

+0

'SetupGet()'在抽象類上工作嗎? – 48klocs 2013-04-09 20:02:42

+1

@ 48klocs是的,但要正確地模擬屬性(或方法),該屬性必須標記爲「abstract」或「virtual」。不幸的是,我無法修改MyDependency類。 – 2013-04-09 20:32:15

回答

3

如果你不能改變屬性爲虛擬或定義一個接口(我假設如果你不能做第一個接口,你將無法做第二個)然後我看到只有兩種可能的選擇:

  • 用嘲弄的框架,確實非虛成員(例如TypeMock)
  • 創建一個特定的模擬實現從MyDependency繼承,你已經做了的支持嘲諷。
1

我明白你問什麼,我認爲你正在尋找的東西是這樣的:

public class Test 
{ 
    public void MockObject() 
    { 
     var mocked = new Moq.Mock<MyDependency>(); 
     mocked.CallBase = true; 
     mocked.Setup(m => m.Outputs).Returns(new Dictionary<string, object>() { { "key", "value" } }); 

     mocked.Object.{do something with mocked object}; 
    } 
} 

...我想你仍然需要在Outputs財產virtual雖然。

+0

是的,爲了使'Setup'工作,'Outputs'屬性上必須有'virtual'關鍵字。不幸的是,對於我來說,修改依賴關係並不是一個真正的選擇,因爲它屬於不同的組。 – 2013-04-09 20:27:19

2

如果您不是自己派生的類,則很難指定protected字段_outputs,因爲它不在範圍內,並且其名稱不會被編譯。

但是你可以用,當然討厭的反射做到這一點:

var mock = new Mock<MyDependency>(); 

var field = typeof(MyDependency) 
    .GetField("_outputs", BindingFlags.Instance | BindingFlags.NonPublic); 
field.SetValue(mock.Object, 
    new Dictionary<string, object> { { "key", "value" } }); 

如果從畢竟MyDependency派生,然後從它派生的類中,你可以設置字段如:

// this code is inside some class which derives from MyDependency 
mock.Object._outputs = new Dictionary<string, object> { { "key", "value" } }; 
1

聲明一個接口,該接口公開MyDependency類所需的成員,然後可以將其與Mo q創建您的測試所需的行爲。

public interface IMyDependency { 
    Dictionary<string, object> Outputs { get; } 
} 

// test... 
var dictionary = new Dictionary<string, string>{{"key", "value"}}; 
var dependency = new Mock<IMyDependency>(); 
dependency.SetupGet(d => d.Outputs).Returns(dictionary); 

當你在你的產品代碼中使用它,您可以在「投」 MyDependency情況下使用DuckTyping(或類似)的接口後面。

相關問題