Comment lancer une SqlException lorsque cela est nécessaire pour des moqueries et des tests unitaires?
Je suis en train de tester quelques exceptions dans mon projet et l'une des Exceptions que je capture est SQlException
.
Il semble que vous ne pouvez pas aller new SqlException()
donc je ne suis pas sûr de savoir comment je peut lancer une exception surtout sans en quelque sorte l'appel de la base de données (et vu que ce sont des tests unitaires, il est généralement conseillé de ne pas appeler la base de données puisque c'est lent).
Je suis à l'aide de NUnit et Moq, mais je ne suis pas sûr de savoir comment ce faux.
De répondre à certaines des réponses qui semblent tous être fondée sur ADO.NET, sachez que je suis à l'aide de Linq to Sql. Donc, ce genre de choses, c'est comme en coulisses.
Plus d'infos tel que demandé par @MattHamilton:
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()
Postes à la première ligne lorsqu'il essaie de maquette
var ex = new Mock<System.Data.SqlClient.SqlException>();
ex.SetupGet(e => e.Message).Returns("Exception message");
- Vous avez raison. J'ai mis à jour ma réponse, mais ce n'est probablement pas très utile maintenant. DbException est probablement la meilleure exception hic cependant, afin de ne prendre en considération.
- Les réponses qui fonctionnent réellement produire une variété de messages d'exception. Définir précisément le type dont vous avez besoin peut être utile. E. g. "J'ai besoin d'une SqlException qui contient le numéro d'exception 18487, en indiquant le mot de passe spécifié a expiré." Semble d'une telle solution est plus appropriée pour les tests unitaires.
Vous devez vous connecter pour publier un commentaire.
Puisque vous êtes à l'aide de Linq to Sql, voici un exemple de test du scénario que vous avez mentionné à l'aide de NUnit et Moq. Je ne connais pas les détails exacts de votre DataContext et ce que vous avez disponibles. Edit pour répondre à vos besoins.
Vous aurez besoin d'envelopper le DataContext avec une classe personnalisée, vous ne pouvez pas se Moquer du DataContext Moq. Vous ne pouvez pas se moquer de SqlException, car il est scellé. Vous aurez besoin de les envelopper avec votre propre classe d'Exception. Il n'est pas difficile à faire ces deux choses.
Commençons par créer notre test:
Nous allons mettre en œuvre le test d'abord laisser envelopper notre Linq to Sql appels à l'aide du modèle de référentiel:
Prochaine créer le IDataContextWrapper comme ça, vous pouvez consulter cette post de blog sur le sujet, le mien diffère un peu:
Prochaine créer le CustomSqlException classe:
Voici un exemple de mise en œuvre de la IDataContextWrapper:
Vous pouvez le faire avec réflexion, vous devez la maintenir lorsque Microsoft apporter des modifications, mais il ne fonctionne pas je l'ai juste testé:
Cela vous permet également de contrôler le Nombre de la SqlException, qui peut être important.
NewSqlException
méthode de lecture:SqlError error = Construct<SqlError>(number, (byte)2, (byte)3, "server name", "error message", "proc", 100, null);
J'ai une solution à cette question. Je ne suis pas sûr de savoir si c'est un coup de génie ou de folie.
Le code suivant va créer un nouveau SqlException:
que vous pouvez ensuite utiliser comme (cet exemple utilise Moq)
de sorte que vous pouvez tester votre SqlException gestion des erreurs dans vos dépôts, les gestionnaires et les contrôleurs.
Maintenant, j'ai besoin d'aller se recoucher.
new SqlConnection(@"Data Source=.;Database=GUARANTEED_TO_FAIL;Connection Timeout=1")
En fonction de la situation, je préfère GetUninitializedObject à l'invocation d'une ConstructorInfo. Vous avez juste à être conscient qu'il n'a pas d'appeler le constructeur de la MSDN Remarques: "Parce que la nouvelle instance de l'objet est initialisé à zéro et aucune constructeurs sont exécutées, l'objet peut ne pas représenter un état qui est considéré comme valable par cet objet." Mais je dirais qu'il est moins cassant que de s'appuyer sur l'existence d'un certain constructeur.
typeof(SqlException).GetField("_message", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(exception, "my custom sql message");
Modifier Ouch: je ne savais pas SqlException est scellé. J'ai été moqueur DbException, qui est une classe abstraite.
Vous ne pouvez pas créer un nouveau SqlException, mais vous pouvez simuler une DbException, qui SqlException dérive. Essayez ceci:
De sorte que votre exception est levée lorsque la méthode tente d'ouvrir la connexion.
Si vous vous attendez à lire autre chose que les
Message
bien sur la moqué d'exception, alors n'oubliez pas d'Attendre (ou de l'Installation, selon votre version de Moq) le "get" sur ces propriétés.Ne sais pas si cela aide, mais semble avoir travaillé pour cette personne (très intelligent).
Trouvé à:
http://smartypeeps.blogspot.com/2006/06/how-to-throw-sqlexception-in-c.html
Cela devrait fonctionner:
Qui prend un peu avant qu'il lève l'exception, donc je pense que ce serait encore plus rapide:
Code apporté à vous par des Hacks-R-Us.
Mise à jour: nope, la deuxième approche, déclenche une exception d'argument, pas une SqlException.
Mise à jour 2: cela fonctionne beaucoup plus rapidement (à l'exception SqlException est levée en moins d'une seconde):
J'ai remarqué que votre question est d'un an, mais pour le dossier je voudrais ajouter une solution que j'ai découvert récemment, à l'aide de microsoft Moles (vous pouvez trouver ici des références à des Microsoft Taupes)
Une fois que vous haved moled le Système.Les données de l'espace de noms, vous pouvez tout simplement se moquer de une exception SQL sur une occurrence de SqlConnection.Open() comme ceci :
J'espère que cela peut aider quelqu'un qui frappe à cette question dans l'avenir.
(Sry c'est 6 mois de retard, j'espère que ça ne sera pas considéré necroposting j'ai atterri ici à la recherche de la façon de lancer un SqlCeException à partir d'une maquette).
Si vous avez juste besoin de tester le code qui gère l'exception d'un ultra simple solution de contournement serait:
Basé sur toutes les autres réponses, j'ai créé la solution suivante:
C'est vraiment vieux et il ya quelques bonnes réponses ici. Je suis à l'aide de Moq, et je ne peux pas se moquer des classes Abstraites et ne voulais vraiment pas à utiliser la réflexion, j'ai donc fait mon propre Exception dérivé de DbException. Donc:
évidemment, si vous avez besoin d'ajouter InnerException, ou que ce soit, ajouter plus d'accessoires, constructeurs, etc.
puis, dans mon test:
Hoepfully cela permettra d'aider toute personne qui est à l'aide de Moq. Merci pour tout le monde qui a posté ici qui m'a conduit à ma réponse.
Je vous suggérons d'utiliser cette méthode.
Vous pouvez utiliser la réflexion pour créer SqlException objet du test:
private SqlException(string message, SqlErrorCollection errorCollection, Exception innerException, Guid conId)