| 

.NET C# Java Javascript Exception

4
Hallo zusammen,

ich habe eine "Adapter" Klasse, mit der ich Hardware steuere. Das ganze ist auch noch ein Singleton. Für meine bisherigen Unit Tests wird im "[ClassInitialize()]" die Instanz geholt und ein Init der Hardware durchgeführt, so dass die ganzen Tests auch parallel ausgeführt werden können. (Voraus gesetzt die Hardware ist angeschlossen.)

Jetzt möchte ich aber gerne noch mal den Fall testen können, dass eine Methode aufgerufen wird, ohne dass initialisiert wurde. Dann soll eine Exception geworfen werden. Ich weiss aber nicht, wie ich MSTest dazu bringen könnte, die zwei Tests noch vor dem ClassInitialize auszuführen.

Selbst wenn ich die beiden Tests in eine eigene Testklasse ohne ClassInitialize packe, kann die andere Testklasse ja schon gestartet worden sein und meinen Singleton - Adapter initialisiert haben. (So passiert es im Moment auch. :( )

Danke,
Mike
23.04.2012
Xantiva 2,3k 2 9
2 Antworten
2
Ich würde das nicht mehr als UnitTest bezeichnen. Aufgrund der externen Abh. (Hardware) ist das mindestens eine Integrationstest. Aber das nur am Rande...
Da ein Test auch ein Nutzer Deiner Klasse ist, spricht nichts dagegen, einer Klasse Funktionalität hinzuzufügen, die für Tests benötigt wird.

In Deinem Fall könntest Du z.B. Deinem Adapter eine Reset()-Methode spendieren, die die Initialisierung zurücksetzt. Normalerweise macht man das durch Ableitung, wie es bei Dir klappen könnte, weißt Du sicher besser.

Für eine bessere Testbarkeit solltest Du das Implementierungsdetail "Singleton" zukünftig zumindest in einer Factory verstecken (oder Dich für Lebenszeitkontrolle auf einen IoC Container verlassen). Dann hast Du im Test wesentlich bessere Möglichkeiten, den Singleton gegen Varianten oder Fakes auszutauschen - durch Ableitung/Fake der Factory. Wobei man einen static Zugriff auf den Singleton mit entsprechenden Tools auch umbiegen kann (Moles, Typemock Isolator, ...)

UPDATE :
Vielleicht hilft das weiter... MSDN: How to: Create an Ordered Test
23.04.2012
ffordermaier 8,4k 3 9
Hi, wenn ich ein Reset aufrufe, dann scheitern wieder die anderen Tests, die parallel ablaufen.
Und die "UnitTests" für solche Hardware nahen Klassen sind hilfreich, insbesondere, weil ich dann z. B. eine neue Version der Hersteller-API auch mit testen kann. Ob damit mein Code dann noch funktioniert.
Xantiva 23.04.2012
Vlt. hilft Dir der Link weiter, den ich eben gefunden habe. Hab ihn in den Post aufgenommen.
ffordermaier 23.04.2012
Wenn ich so eine Testreihe (Ordered Test) erstelle und dort meine beiden Tests hinzufüge, dann werden diese vor allen anderen Tests ausgeführt. Das passt schon mal. Wenn ich über die einfache Testansicht alle Tests markiere, dann werden die Tests zwar noch mal ausgeführt und scheitern dann (logisch), aber wenn ich irgendwann mal ein CI - System nutzen sollte, wird man dass auch noch in den Griff bekommen.

Danke, Mike
Xantiva 23.04.2012
Cool *thumbs up*
Nicolai Schönberg 23.04.2012
1
Puh, das ist schon ziemlich speziell muss ich sagen... Es gibt noch ein AssemblyInitialize Attribut.

Zitat MSDN
The method marked with this attribute will be run before methods marked with the ClassInitializeAttribute, TestInitializeAttribute, and TestMethodAttribute attributes. Only one method in an assembly may be decorated with this attribute.


Aber ich weiß nicht, ich find das ziemlich hässlich tbh. Du könntest das machen um dein Singleton-Problem zu umgehen. So richtig sauber finde ich den Ansatz aber nicht.

Was ich besser finden würde:

  • Setze deine Methode welche die Exception wirft auf Internal, mach sie mit hilfe von InternalsVisibleTo in deinem Testprojekt verfügbar und teste den wurf der Exception mit dem ExpectedException Attribut

  • oder falls du sowas hast wie "Hardware erfolgreich initialisiert" dann merk dir diesen bool Wert in deiner Klasse. Für einen Test könntest du ihn dann auf False setzen um die Methode auszuführen welche deine Exception wirft


Das mit dem AssemblyInitialize würde sicher funktionieren, aber auf lange Sicht wird das ziemlich unübersichtlich wenn du verschiedene zeitliche Faktoren in deine Tests einbaust .. Die sollten besser alle unabhängig voneinander funktionieren.

Grüße
23.04.2012
Nicolai Schönberg 2,4k 2 9
Hi, das AssemblyInitialize habe ich auch schon gelesen, aber das hilft mir doch nicht? Ich habe eine "TestMethod", die ich zu einem bestimmten Zeitpunkt ausführen muss. Mit dem AssemblyInitialize könnte ich doch nur "etwas vorbereiten", bevor die Klasse initialisiert wird, oder?
Die beiden anderen Ansätze funktionieren leider auch nicht, da ja parallel die anderen Tests ausgeführt werden, die eine Initialisierung erfordern. Dann würden diese Tests ggf. wieder scheitern.
Xantiva 23.04.2012

Stelle deine Unit-testing-Frage jetzt!