2008-09-16 45 views
6

目前,我从潜入全面进入单元测试的最大问题之一是,我写的代码中的很大比例很大程度上依赖于来自不同源的第三方COM对象,这些对象也倾向于相互交互(如果您需要了解,我正在使用多个帮助程序库为Microsoft Office编写加载项)。你如何单元测试与第三方COM对象交互并实例化的代码?

我知道我应该使用模拟对象,但在这种情况下我会如何处理?我可以看到,当我只需要传递一个对已经存在的对象的引用时,它相对容易,但是我的一些例程本身实例化外部COM对象,然后有时将它们从另一个库传递给某个其他外部COM对象。

这里最好的做法是什么?我是否应该让我的测试代码临时更改注册表中的COM注册信息,以便测试代码将实例化我的一个模拟对象?我应该注入修改过的类型库单元吗?还有哪些其他方法?

我将特别感谢Delphi的示例或工具,但同样会对更一般的建议和更高级别的解释感到满意。

感谢,

奥利弗

回答

6

传统的做法说,你的客户端代码应该使用的包装,这是负责实例化COM对象。这个包装可以很容易地嘲笑。

因为你已经有部分代码直接实例化COM对象,所以这并不适合。如果您可以更改该代码,则可以使用工厂模式:他们使用工厂创建COM对象。你可以模拟工厂返回替代对象。

对象是通过包装器还是通过原始COM接口访问取决于您。如果你选择模拟COM接口,记得在你的模拟器中使用IUnknown :: QueryInterface,这样你就知道你已经模拟了所有的接口,特别是当对象被传递给其他COM对象时。

或者,查看CoTreateAsClass方法。我从来没有用过它,但它可能会做你所需要的。

3

它归结为 '设计的可测试性'。理想情况下,您不应该直接实例化这些COM对象,而应该通过可以由模拟对象替换的间接层来访问它们。

现在,COM本身确实提供了一个间接的级别,你可以提供一个模拟对象,它提供了一个替代真实的模拟对象,但我怀疑创建会很痛苦,我怀疑你是否能从现有的嘲笑框架。

+0

同意;并且因为所有与COM对象的交互(除了通过IDispatch的自动化调用)都使用COM接口,您应该只能够在您的模拟类中实现这些接口。 – rpetrich 2008-09-16 09:07:20

2

我会围绕你的第三方COM对象编写一个薄包装类,它能够在单元测试情况下加载模拟对象而不是实际的COM对象。我通常通过让第二个构造函数来调用传递给模拟对象。正常的构造函数会像平常一样加载COM对象。

维基百科的文章有一个很好的介绍主题 Wikipedia artible