[英]Mocking and Marshal.ReleaseComObject()
我在設置模擬時遇到問題,所以我可以在我的Mocked對象上調用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);
}
}
}
它在我使用真實的特征光標和特征時有效,但是當我在單元測試中模擬該特征時,我得到一個錯誤:
"System.ArgumentException : The object's type must be __ComObject or derived from __ComObject."
但是如何將其應用於我的Mock對象?
Mocked IFeature
只是一個標准的.NET類,而不是COM
對象,這就是為什么你的測試當前正在拋出的The object's type must be __ComObject...
exception。
你只需要調用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));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.