2008-09-16 6 views
6

Eines der größten Probleme, die mich derzeit davon abhalten, Volldampf in Komponententests zu tauchen, ist, dass ein wirklich großer Prozentsatz des von mir geschriebenen Codes stark von COM-Objekten von Drittanbietern aus verschiedenen Quellen abhängt, die auch miteinander interagieren (Ich schreibe Add-Ins für Microsoft Office mit mehreren Hilfs-Bibliotheken, wenn Sie wissen müssen).Wie testen Sie Unit-Code, der mit COM-Objekten von Drittanbietern interagiert und instanziiert?

Ich weiß, ich sollte wahrscheinlich Mock-Objekte verwenden, aber wie genau würde ich in diesem Fall darüber gehen? Ich kann sehen, dass es relativ einfach ist, wenn ich nur einen Verweis auf ein bereits vorhandenes Objekt weitergeben muss, aber einige meiner Routinen instanziieren externe COM-Objekte selbst und geben sie dann manchmal an ein anderes externes COM-Objekt aus einer anderen Bibliothek weiter.

Was ist der Best-Practice-Ansatz hier? Soll ich den Testcode vorübergehend ändern, um die COM-Registrierungsinformationen in der Registrierung zu ändern, damit der getestete Code stattdessen eines meiner Mock-Objekte instanziiert? Sollte ich modifizierte Typ-Bibliothekseinheiten injizieren? Welche anderen Ansätze gibt es?

Ich wäre besonders dankbar für Beispiele oder Tools für Delphi, wäre aber genauso glücklich mit allgemeineren Hinweisen und Erklärungen auf höherer Ebene.

Danke,

Oliver

Antwort

6

Der traditionelle Ansatz besagt, dass Ihr Client-Code einen Wrapper verwenden sollten, die für die Instanziierung des COM-Objekt zuständig ist. Dieser Wrapper kann dann leicht verspottet werden.

Da Teile Ihres Codes die COM-Objekte direkt instanziieren, passt dies nicht wirklich. Wenn Sie diesen Code ändern können, können Sie das Factory-Muster verwenden: Sie verwenden die Factory, um das COM-Objekt zu erstellen. Sie können sich über die Factory lustig machen, um alternative Objekte zurückzugeben.

Ob Sie über einen Wrapper oder über die ursprüngliche COM-Schnittstelle auf das Objekt zugreifen, bleibt Ihnen überlassen. Wenn Sie sich dafür entscheiden, die COM-Schnittstelle zu verspotten, denken Sie daran, IUnknown :: QueryInterface in Ihrem Mock zu instrumentieren, damit Sie wissen, dass Sie alle Schnittstellen verspottet haben, insbesondere wenn das Objekt dann an ein anderes COM-Objekt übergeben wird.

Alternativ, überprüfen Sie die CoTreateAsClass Methode. Ich habe es nie benutzt, aber es könnte tun, was Sie brauchen.

3

Es kommt auf die 'Gestaltung für Testbarkeit'. Im Idealfall sollten Sie diese COM-Objekte nicht direkt instanziieren, sondern sollten auf sie über eine Indirektionsebene zugreifen, die durch ein Mock-Objekt ersetzt werden kann.

Nun, COM selbst bietet eine Ebene der Umleitung und Sie könnten ein Mock-Objekt zur Verfügung stellen, die einen Ersatz für die echte, aber ich vermute, es wäre ein Schmerz zu schaffen, und ich bezweifle, wenn Sie viel Hilfe bekommen würde ein existierendes Spott-Framework.

+0

Einverstanden; Da alle Interaktionen mit COM-Objekten (außer Automatisierungsaufrufen über IDispatch) eine COM-Schnittstelle verwenden, sollten Sie diese nur in Ihrer Scheinklasse implementieren können. – rpetrich

2

Ich würde eine dünne Wrapper-Klasse um Ihr COM-Objekt von Drittanbietern schreiben, das die Möglichkeit hat, ein Mock-Objekt anstelle des tatsächlichen COM-Objekts in der Einheitstestsituation zu laden. Normalerweise mache ich das, indem ich einen zweiten Konstruktor habe, den ich rufe, indem ich das Mock-Objekt übergebe. Der normale Konstruktor hätte das COM-Objekt gerade normal geladen.

Wikipedia-Artikel hat eine gute Einführung in das Thema Wikipedia artible