Besetzt mit automatisierten Testfällen in C #, und wir müssen nach jedem Test einen DB-Snapshot wiederherstellen. Problem ist, wenn mehrere Tests ausgeführt werden, schlägt es fehl, weil der "Datenbankstatus nicht geändert werden kann, während andere Benutzer die Datenbank verwenden."
Wir verwenden SqlConnection.ClearAllPools();
vor der Wiederherstellung, aber nach dem vierten Test wird es nicht wieder für den Lauf wiederhergestellt, und es scheint, dass die Pools aufhören zu löschen. (Warum vier? Siehe Bearbeiten 2)
Wie kann ich das zuverlässiger machen?
BEARBEITEN
Vielleicht sollte ich mehr Informationen über das System geben. Dies sind Unit Integrationstests für einen Service. Die Tests verweisen auf die Service-DLL (keine Service-Referenz, wir greifen direkt auf die Service-Methoden zu). Daher gibt es in den Tests keine andere SQL als den DB-Snapshot nach jedem Testblock wiederherzustellen.
Dies ist ein Dienst, daher verwalten wir die Verbindungen nicht genau. Wir haben einen zentralen Punkt, an dem wir die Datenbankobjekte erstellen, von denen wir unsere DbCommands erhalten, um gespeicherte Prozeduren auszuführen.
Wenn ich sp_who2
in SQL Studio verwende, beobachte ich Folgendes: Es gibt eine Sitzung in der Datenbank für die ersten vier Testblöcke (wobei jeder Block durch ein ClearAllPools()
und eine Momentaufnahme-Wiederherstellung getrennt ist), aber ab dem Fünfter Testblock Es gibt drei Sitzungen dagegen. (Warum? Dies könnte ein Hinweis auf das Problem sein.) (Die Wiederherstellung des Snapshots öffnet eine zusätzliche Verbindung zur Master-DB.) Alle offenen Verbindungen haben den Status "Sleeping" und warten auf den Befehl, sogar den, der die Snapshot-Wiederherstellung blockiert.
BEARBEITEN 2
Warum fünf? Ich dachte, die Testfälle würden zufällig ausgeführt werden, aber ich lag falsch. Ich habe den Schuldigen gefunden. Es werden mehr als eine Verbindung geöffnet, das System verwendet nur die letzte, und die anderen bleiben hängen und werden erst gelöscht, wenn Sie die Verbindung verlassen.
Bevor Sie den Snapshot wiederherstellen, legen Sie die Datenbank im Einzelbenutzermodus fest:
%Vor%Wenn Sie die offenen Verbindungen nicht beenden möchten, können Sie den Befehl warten, indem Sie ihn ohne die Rollback-Option ausführen
%Vor%Es ist ein Hack, aber es ist sehr schwierig, Ihre Snapshot-Wiederherstellung sonst konsistent zu machen. (einmal gebissen, zweimal schüchtern.)
Ich verwende einen anderen Ansatz. Ich führe die Tests in einer Transaktion durch, die am Ende jedes Tests entsorgt wird (Rollback). Auf diese Weise müssen Sie die Datenbank nicht bei jeder Testsitzung wegschmeißen, da die Datenbank immer "sauber" ist. In C # können Sie ein TransactionScope erstellen und nach dem Test ablegen, oder (besser) wenn Sie xUnit.net verwenden, können Sie das AutoRollback-Attribut verwenden.
Wir machen das Gleiche. Stellen Sie die Datenbank vor jedem Test wieder her:
%Vor%Für den Fall, dass die Datenbank noch nicht existiert, prüfen wir dies mit
%Vor%Hoffe, das hilft
Tags und Links sql c# unit-testing integration-testing snapshot