Ich versuche, einige Ausnahmen in meinem Projekt zu testen, und eine der Ausnahmen, die ich fange, ist SQlException
.
Es scheint, dass Sie nicht gehen können, new SqlException()
daher bin ich mir nicht sicher, wie ich eine Ausnahme auslösen kann, insbesondere ohne die Datenbank aufzurufen (und da es sich um Komponententests handelt, wird normalerweise empfohlen, die Datenbank nicht aufzurufen, da sie langsam ist).
Ich benutze NUnit und Moq, bin mir aber nicht sicher, wie ich das vortäuschen soll.
Beachten Sie, dass ich bei der Beantwortung einiger Antworten, die anscheinend alle auf ADO.NET basieren, Linq to Sql verwende. Das Zeug ist also wie hinter den Kulissen.
Weitere Informationen wie von @MattHamilton angefordert:
System.ArgumentException : Type to mock must be an interface or an abstract or non-sealed class.
at Moq.Mock`1.CheckParameters()
at Moq.Mock`1..ctor(MockBehavior behavior, Object[] args)
at Moq.Mock`1..ctor(MockBehavior behavior)
at Moq.Mock`1..ctor()
Beiträge in der ersten Zeile, wenn versucht wird, ein Modell zu erstellen
var ex = new Mock<System.Data.SqlClient.SqlException>();
ex.SetupGet(e => e.Message).Returns("Exception message");
quelle
Antworten:
Da Sie Linq to Sql verwenden, finden Sie hier ein Beispiel zum Testen des von Ihnen erwähnten Szenarios mit NUnit und Moq. Ich kenne die genauen Details Ihres DataContext nicht und weiß nicht, was Sie darin zur Verfügung haben. Bearbeiten Sie für Ihre Bedürfnisse.
Sie müssen den DataContext mit einer benutzerdefinierten Klasse umschließen. Sie können den DataContext nicht mit Moq verspotten. Sie können SqlException auch nicht verspotten, da es versiegelt ist. Sie müssen es mit Ihrer eigenen Ausnahmeklasse umschließen. Es ist nicht allzu schwierig, diese beiden Dinge zu erreichen.
Beginnen wir mit der Erstellung unseres Tests:
Lassen Sie uns den Test implementieren. Lassen Sie uns zuerst unsere Linq-to-Sql-Aufrufe mit dem Repository-Muster umbrechen:
Als nächstes erstellen Sie den IDataContextWrapper so, dass Sie diesen Blog-Beitrag zu diesem Thema anzeigen können , meiner unterscheidet sich ein wenig:
Erstellen Sie als Nächstes die CustomSqlException-Klasse:
Hier ist eine Beispielimplementierung des IDataContextWrapper:
quelle
Sie können dies mit Reflection tun. Sie müssen es beibehalten, wenn Microsoft Änderungen vornimmt, aber es funktioniert. Ich habe es gerade getestet:
Auf diese Weise können Sie auch die Nummer der SqlException steuern, was wichtig sein kann.
quelle
NewSqlException
Methode wie folgt :SqlError error = Construct<SqlError>(number, (byte)2, (byte)3, "server name", "error message", "proc", 100, null);
Ich habe eine Lösung dafür. Ich bin mir nicht sicher, ob es Genie oder Wahnsinn ist.
Der folgende Code erstellt eine neue SqlException:
die Sie dann so verwenden können (dieses Beispiel verwendet Moq)
Damit können Sie Ihre SqlException-Fehlerbehandlung in Ihren Repositorys, Handlern und Controllern testen.
Jetzt muss ich mich hinlegen.
quelle
new SqlConnection(@"Data Source=.;Database=GUARANTEED_TO_FAIL;Connection Timeout=1")
Je nach Situation ziehe ich GetUninitializedObject normalerweise dem Aufrufen einer ConstructorInfo vor. Sie müssen sich nur bewusst sein, dass der Konstruktor nicht aufgerufen wird - aus dem MSDN. Anmerkungen: "Da die neue Instanz des Objekts auf Null initialisiert wird und keine Konstruktoren ausgeführt werden, repräsentiert das Objekt möglicherweise keinen Status, der als gültig angesehen wird von diesem Objekt. " Aber ich würde sagen, es ist weniger spröde, als sich auf die Existenz eines bestimmten Konstruktors zu verlassen.
quelle
typeof(SqlException).GetField("_message", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(exception, "my custom sql message");
Edit Autsch: Ich wusste nicht, dass SqlException versiegelt ist. Ich habe DbException verspottet, eine abstrakte Klasse.
Sie können keine neue SqlException erstellen, aber Sie können eine DbException verspotten, von der SqlException abgeleitet ist. Versuche dies:
Ihre Ausnahme wird also ausgelöst, wenn die Methode versucht, die Verbindung zu öffnen.
Wenn Sie erwarten, etwas anderes als die
Message
Eigenschaft in der verspotteten Ausnahme zu lesen, vergessen Sie nicht, das "get" für diese Eigenschaften zu erwarten (oder Setup, abhängig von Ihrer Moq-Version).quelle
Ich bin mir nicht sicher, ob dies hilft, scheint aber für diese Person funktioniert zu haben (ziemlich klug).
Gefunden unter: http://smartypeeps.blogspot.com/2006/06/how-to-throw-sqlexception-in-c.html
quelle
Das sollte funktionieren:
Es dauert ein bisschen, bis die Ausnahme ausgelöst wird. Ich denke, das würde noch schneller funktionieren:
Code von Hacks-R-Us.
Update : Nein, der zweite Ansatz löst eine ArgumentException aus, keine SqlException.
Update 2 : Dies funktioniert viel schneller (die SqlException wird in weniger als einer Sekunde ausgelöst):
quelle
Ich habe festgestellt, dass Ihre Frage ein Jahr alt ist, aber für die Aufzeichnung möchte ich eine Lösung hinzufügen, die ich kürzlich mit Microsoft Moles entdeckt habe (Referenzen finden Sie hier Microsoft Moles ).
Sobald Sie den System.Data-Namespace geändert haben, können Sie einfach eine SQL-Ausnahme in einer SqlConnection.Open () wie folgt verspotten:
Ich hoffe, dies kann jemandem helfen, der diese Frage in Zukunft beantwortet.
quelle
(Sry, es ist 6 Monate zu spät, ich hoffe, dies wird nicht als Nekroposting angesehen. Ich bin hier gelandet und habe nach einer Möglichkeit gesucht, eine SqlCeException aus einem Mock zu werfen.)
Wenn Sie nur den Code testen müssen, der die Ausnahme behandelt, wäre eine extrem einfache Problemumgehung:
quelle
Basierend auf all den anderen Antworten habe ich die folgende Lösung erstellt:
quelle
Das ist wirklich alt und hier gibt es einige gute Antworten. Ich verwende Moq und kann abstrakte Klassen nicht verspotten und wollte wirklich keine Reflexion verwenden. Deshalb habe ich meine eigene Ausnahme erstellt, die von DbException abgeleitet ist. So:
Wenn Sie InnerException oder was auch immer hinzufügen müssen, fügen Sie natürlich weitere Requisiten, Konstruktoren usw. hinzu.
dann in meinem Test:
Hoffentlich hilft dies jedem, der Moq verwendet. Vielen Dank für alle, die hier gepostet haben und mich zu meiner Antwort geführt haben.
quelle
Ich schlage vor, diese Methode zu verwenden.
quelle
SqlException
es keinen Konstruktor gibt underrorConstructor
null ist.Diese Lösungen fühlen sich aufgebläht.
Der CTOR ist intern, ja.
(Ohne Reflexion ist dies der einfachste Weg, um diese Ausnahme wirklich zu erstellen.
Perphaps gibt es eine andere Methode, für deren Werfen keine Zeitüberschreitung von 1 Sekunde erforderlich ist.
quelle
Sie können Reflection verwenden, um ein SqlException-Objekt im Test zu erstellen:
quelle
private SqlException(string message, SqlErrorCollection errorCollection, Exception innerException, Guid conId)