Comment se fait que vous ne pouvez pas attraper Contrat de Code exceptions?
Système.Diagnostics.Des contrats.ContractException n'est pas accessible dans mon projet de test. Remarque: ce code est purement moi-même de déconner avec mes shiney nouvelle copie de Visual Studio, mais j'aimerais savoir ce que je fais mal.
Je suis à l'aide de l'édition professionnelle de VS, donc je n'ai pas de vérification statique. Afin de toujours utiliser des contrats de code (que j'aime) j'ai pensé que la seule façon de ma méthode de travail est d'attraper l'exception est levée lors de l'exécution, mais je ne suis pas à trouver ce possible.
TestMethod
[TestMethod, ExpectedException(typeof(System.Diagnostics.Contracts.ContractException))]
public void returning_a_value_less_than_one_throws_exception()
{
var person = new Person();
person.Number();
}
Méthode
public int Number()
{
Contract.Ensures(Contract.Result<int>() >= 0);
return -1;
}
Erreur
Erreur De 1 'Système.Diagnostics.Des contrats.ContractException' est inaccessible en raison de son niveau de protection.
Modifier
Après certains plus de pensée, je suis venu à la conclusion discuté dans les commentaires, ainsi que les suivants. Étant donné une méthode, si cela avait une exigence qui peut être exprimé dans le Code du formulaire de Contrat, je ferais des tests en tant que tel.
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void value_input_must_be_greater_than_zero()
{
//Arrange
var person = new Person();
//Act
person.Number(-1);
}
Cela permettrait de s'assurer que le contrat est une partie du code, il ne sera pas supprimé. Ceci nécessiterait un Contrat de Code pour réellement lancer l'exception spécifiée, cependant. Dans certains cas, cela ne serait pas nécessaire, cependant.
- Je dois ajouter que cela ne compile pas, naturellement.
- J'aimerais vraiment voir NUnit déprécier ExpectedExceptionAttribute. Exception Affirme vous donner beaucoup plus de contrôle.
- Votre souhait est enfin arrivé avec NUnit 3.0: github.com/nunit/nunit/wiki/Breaking-Changes#body
Vous devez vous connecter pour publier un commentaire.
C'est délibéré - bien qu'une légère douleur pour les tests.
Le point est que dans le code de production ne doit jamais vous voulez prendre un contrat d'exception; il indique un bug dans votre code, vous ne devriez pas attendre plus que arbitraire exceptions inattendues qui peuvent vous voulez prendre à droite en haut de votre pile d'appel de sorte que vous pouvez passer à la prochaine demande. Fondamentalement, vous ne devriez pas voir contrat d'exceptions qui peuvent être "gérée" en tant que tel.
Maintenant, pour les tests c'est une douleur... mais avez-vous vraiment envie de tester vos contrats de toute façon? N'est-ce pas un peu comme les tests que le compilateur ne vous empêche de passer dans un
string
une méthode qui a unint
paramètre? Vous avez déclaré le contrat, il peut être documentés de façon appropriée, et appliquées de manière appropriée (en fonction de paramètres, de toute façon).Si vous ne voulez tester contrat exceptions, vous pouvez prendre un nu
Exception
dans le test et la vérification de son nom complet, ou vous pouvez s'amuser avec lesContrat.ContractFailed
événement. J'attendrais les tests unitaires des cadres pour la prise en charge intégrée pour cela, au fil du temps - mais ça va prendre un peu de temps pour y arriver. En attendant, vous souhaitez probablement une méthode utilitaire de s'attendre à une violation de contrat. Une implémentation possible:void M(string s)
exige queM
jeter sis
est null ou un espace blanc. Une façon de mettre en œuvre consiste à utiliserContract.Requires
. Une autre manière classique, c'est laif-throw
construire, ou éventuellement utiliser un haut -Guard.Against
. Le point est, un test ne devrait pas être l'essai le contrat, mais queM
est conforme à la spécification.void M(string s)
qui jette sis
est nul ou blanc de l'espace et sinon imprimes
à la console, qui est la spécification. Je risque de ne pas mettre pleinement en œuvre la spécification par négliger d'inclure unContract.Requires
ou unif-throw
construire. Le point de l'unité de test est de s'assurer que je mettre pleinement en œuvre le cahier des charges, ainsi que de les protéger contre le refactoring et de maintenance.void M(string s)
avec unint
paramètre. Le test unitaire doit code de test comportement, donc si je m'attends à une exception lorsque je l'appelle avec la valeur null, alors je devrais être en mesure de vérifier le comportement à adopter avec un test unitaire.EDIT: j'ai eu une conversion et de ne plus utiliser ExpectedException ou cet attribut ci-dessous, mais plutôt codé des méthodes d'extension:
Ces permettez-moi d'être plus précis sur l'endroit où l'exception est soulevée.
Exemple de ContractFailure méthode:
dans le vs2010 rtm, le nom complet a été changé pour "le Système de.Diagnostics.Des contrats.__ContractsRuntime+ContractException". HTH
Si cette question se fait vieux, et la réponse a déjà été fournie, je me sens comme j'ai une belle solution qui garde les choses simples et lisibles.
En fin de compte, il nous permet d'écrire des tests sur les conditions préalables aussi simple que:
Ok, donc l'idée est de fournir le Code de Contrats de graveur avec un contrat personnalisé d'exécution de la classe.
Ce peut être configuré dans l'assemblée des propriétés dans la section "Custom Graveur Méthodes" (voir le Code des Contrats Manuel de l'Utilisateur section 7.7):
N'oubliez pas aussi de vérifier
Call-site Requires Checking
!La classe personnalisée ressemble à quelque chose comme ceci:
À l'aide d'un custom
PreconditionException
classe (il ne contient rien de fantaisie!).Nous avons en outre l'ajout d'une petite classe d'aide:
Cela nous permet d'écrire simple, lisible essais sur la condition des violations, comme indiqué ci-dessus.