2014-02-12 27 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