2008-11-20 103 views
2

我一直在爲一個只能接收和返回字符串的COM對象進行封裝。對於COM對象的接口看起來是這樣的:嘲笑COM對象

interface IMapinfo 
    { 
     void Do(string cmd); 
     string Eval(string cmd); 
    } 

現在我已經取得類,包基本功能,像這樣:

public class Table 
    { 
     IMapinfo MI; 
     public string Name 
     { 
      //pass the command to the COM object and get back the name. 
      get{return MI.Eval("TableInfo(1,1")");} 
     } 

    } 

現在我想這樣做這些類的單元測試,而無需每次創建真正的COM對象,建立世界然後運行測試。所以我一直在研究使用模擬對象,但我對如何在這種情況下使用嘲諷有點困惑。

我打算用起訂量,所以我寫了這個實驗是這樣的:

 [Test] 
     public void MockMapinfo() 
     { 
      Moq.Mock<Table> MockTable = new Moq.Mock<Table>(); 
      MockTable.ExpectGet(n => n.Name) 
       .Returns("Water_Mains"); 

      Table table = MockTable.Object; 
      var tablename = table.Name; 

      Assert.AreEqual("Water_Mains", tablename,string.Format("tablename is {0}",tablename)); 
      Table d = new Table(); 
     } 

這是嘲笑我的COM對象的正確方法?這個字符串發送到eval函數的真實性如何?還是我這樣做都錯了?

+0

什麼與反對票? – 2008-12-08 13:35:01

回答

3

這是複製嗎? How would I do TDD with a COM OLE object

編輯:看起來像你問同樣的問題,但驗證你的嘲笑代碼(OOPS)。

你不太適合你的嘲笑場景。你是對的,你想要隔離外部依賴,並且你的COM對象肯定符合這個標準。雖然我不是moq的傢伙(我更喜歡RhinoMocks),但模擬背後的想法是互動測試...

互動測試是關於如何凝聚力的對象集合在一起工作。在這種情況下,一個有效的測試是編寫一個依賴於你的COM對象行爲的組件的測試。

在這種情況下,您的「表」就像COM對象的包裝一樣,也取決於COM對象的行爲。爲了說明起見,我們假設您的Table對象針對COM對象返回的值執行自定義邏輯。

現在你可以爲你的Table對象編寫獨立的測試,而使用Mocks模擬你的COM對象的行爲。

public class Table 
{ 
    public Table(IMapInfo map) 
    { 
     _map = map; 
    } 

    public string Name 
    { 
     get 
     { 
     string value = _map.Eval("myexpression"); 
     if (String.IsNullOrEmpty(value)) 
     { 
      value = "none"; 
     } 
     return value; 
     } 
    } 

    private IMapInfo _map; 
} 

[TestFixture] 
public class TableFixture // is this a pun? 
{ 
    [Test] 
    public void CanHandleNullsFromCOM() 
    { 
     MockRepository mocks = new MockRepository(); // rhino mocks, btw 
     IMapInfo map = mocks.CreateMock<IMapInfo>(); 

     using (mocks.Record()) 
     { 
      Expect.Call(map.Eval("myexpression").Return(null); 
     } 

     using (mocks.PlayBack()) 
     { 
      Table table = new Table(map); 
      Assert.AreEqual("none", table.Name, "We didn't handle nulls correctly."); 
     } 

     mocks.verify(); 
    } 
} 

也許你的COM對象在被調用時拋出異常,或者它可能不能很好地處理字符串表達式。實際上,我們正在測試我們的Table對象如何與IMapInfo交互,而不與COM對象的實現綁定。我們還強制執行Table和IMapInfo之間的關係,因爲IMapInfo對象在測試期間必須被調用。

希望這會有所幫助。

+0

軟是,但那時我只是使用直COM對象來傳遞字符串,現在我有一堆字符串經過的層,如果這是有道理的。 – 2008-11-20 06:22:19