2014-02-12 72 views
4

我有一個設置模擬的問題,所以我可以在我的Mocked對象上調用Marshal.ReleaseComObject()Mocking and Marshal.ReleaseComObject()

我正在使用Moq來設置一個類型IFeature(來自第三方接口庫)的模擬。模擬的設置是相當簡單:

var featureMock = new Mock<IFeature>(); 
    IFeature feature = featureMock.Object; 

在我的代碼,在while循環被創建的特徵對象,通過型光標(FeatureCursor)的運行。由於第三方庫的遺留問題,Feature對象存在已知的內存泄漏問題。因此,我必須通過Marshal.ReleaseComObject()釋放對象,如代碼所示;

public class XXX 
{ 

     public void DoThis() 
     { 
     IFeatureCursor featureCursor; 
     //...fill the cursor with features; 

     IFeature feature = null; 
     while ((feature = featureCursor.NextFeature)!= null) 
     { 
      //Do my stuff with the feature 
      Marshal.ReleaseComObject(feature); 
     } 

     } 

} 

它工作時,我用真實的一個featurecursor和功能,但是當我嘲笑功能的單元測試,我得到一個錯誤:

"System.ArgumentException : The object's type must be __ComObject or derived from __ComObject." 

但是我怎麼申請這個我莫克目的?

回答

5

嘲笑IFeature將只是一個標準的.NET類,而不是一個COM對象這就是爲什麼你的測試目前正在拋出The object's type must be __ComObject...例外。

你只需要調用換到Marshal.ReleaseComObject(feature);和檢查對象是否是一個COM對象第一:

if (Marshal.IsComObject(feature) 
{ 
    Marshal.ReleaseComObject(feature); 
} 

那麼你的測試將工作證,但不會叫Marshal.ReleaseComObject(產品代碼將它稱爲)。

因爲它聽起來像你真的想驗證Marshal.ReleaseComObject被代碼調用,你將需要做更多的工作。

因爲它是一個靜態方法實際上並沒有做任何對象本身,你唯一的選擇是創建一個包裝:

public interface IMarshal 
{ 
    void ReleaseComObject(object obj); 
} 

public class MarshalWrapper : IMarshal 
{ 
    public void ReleaseComObject(object obj) 
    { 
     if (Marshal.IsComObject(obj)) 
     { 
      Marshal.ReleaseComObject(obj); 
     } 
    } 
} 

然後讓你的代碼依賴於IMarshal您還可以模擬在你的測試和驗證中:

public void FeaturesAreReleasedCorrectly() 
{ 
    var mockFeature = new Mock<IFeature>(); 
    var mockMarshal = new Mock<IMarshal>(); 

    // code which calls IFeature and IMarshal 
    var thing = new Thing(mockFeature.Object, mockMarshal.Object); 
    thing.DoThis(); 

    // Verify that the correct number of features were released 
    mockMarshal.Verify(x => x.ReleaseComObject(It.IsAny<IFeature>()), Times.Exactly(5)); 
} 
+0

漂亮!!非常感謝你。我爲什麼不考慮製作MarshalWrapper?我在我的代碼中包含了其他所有內容:-) – Morten