Comment vérifier qu'une exception n'a pas été levée
Dans mon unité de test à l'aide de Mockito je veux vérifier que NullPointerException
n'a pas été levée.
public void testNPENotThrown{
Calling calling= Mock(Calling.class);
testClass.setInner(calling);
testClass.setThrow(true);
testClass.testMethod();
verify(calling, never()).method();
}
Mon test mis en place le testClass
réglage de la Calling
de l'objet et de la propriété, de sorte que la méthode de jeter une NullPointerException
.
Je vérifier que l'Appel.méthode() n'est jamais appelée.
public void testMethod(){
if(throw) {
throw new NullPointerException();
}
calling.method();
}
Je veux avoir un test en échec parce qu'il jette à un NullPointerException
et puis je veux écrire un peu de code pour résoudre ce problème.
Ce que j'ai remarqué, c'est que le test passe toujours comme l'exception n'est jamais jeté la méthode de test.
source d'informationauteur walsh_j
Vous devez vous connecter pour publier un commentaire.
tl;dr
pré-JDK8 : je vais recommander le bon vieux
try
-catch
bloc.post-JDK8 : Utilisation AssertJ ou personnalisé lambdas pour affirmer exceptionnelle comportement.
la longue histoire
Il est possible d'écrire vous-même un le faire vous-même
try
-catch
bloc ou utiliser JUnit outils (@Test(expected = ...)
ou la@Rule ExpectedException
JUnit fonction de règle).Mais ce chemin ne sont pas si élégant et ne se mélangent pas bien lisibilité sage avec d'autres outils.
La
try
-catch
bloc, vous devez écrire le bloc autour de l'essai de comportement, et d'écrire l'affirmation dans le bloc catch, qui peut être bien, mais beaucoup trouvent que ce style interrompt la lecture d'un test. Aussi, vous devez écrire unAssert.fail
à la fin de latry
bloc sinon le test peut manquer d'un côté de la assertions ; PMDfindbugs ou Sonar permettra de repérer de tels problèmes.La
@Test(expected = ...)
fonctionnalité est intéressante car vous pouvez écrire moins de code, puis l'écriture de ce test est censé être moins sujettes à des erreurs de codage. Mais sat approche manque un certains domaines.Aussi que l'attente est placé autour de la méthode, selon la façon dont le code testé est écrit ensuite la mauvaise partie du code de test peut jeter l'exception, conduisant à des résultats faussement positifs et je ne suis pas sûr que PMDfindbugs ou Sonar vous donnera des informations sur ce type de code.
La
ExpectedException
règle est aussi une tentative pour résoudre les précédentes mises en garde, mais il se sent un peu difficile à utiliser, car il utilise une attente de style, EasyMock utilisateurs sait très bien ce style. Il peut être pratique pour certains, mais si vous suivez Comportement du Développement Piloté par (BDD) ou Organiser Acte Affirmer (AAA) principes de laExpectedException
règle ne rentre pas dans ceux du style d'écriture. Côté de qui il peut souffrir de la même question que le que le@Test
façon, selon l'endroit où vous placez l'attente.Même attendus exception est placé avant le test, les pauses de votre lecture si l'on procède à des tests BDD ou AAA.
Aussi voir ce commentaire question sur JUnit de l'auteur de
ExpectedException
.De sorte que ces options ont toutes leur charge de mises en garde, et clairement pas à l'abri de coder les erreurs.
Il y a un projet que j'ai pris conscience après la création de cette réponse qui semble prometteur, c'est catch-exception.
Que la description du projet, dit-il permettre à un programmeur d'écrire dans un fluide de ligne de code de capture de l'exception et offre cette exception pour plus tard affirmation. Et vous pouvez utiliser n'importe quelle affirmation de la bibliothèque comme Hamcrest ou AssertJ.
Un rapide exemple tiré de la page d'accueil :
Comme vous pouvez le voir, le code est très simple, vous prenez exception sur une ligne spécifique, la
then
API est un alias qui va utiliser AssertJ Api (similaire à l'aide deassertThat(ex).hasNoCause()...
). À un certain point, le projet reposait sur FEST-Assert l'ancêtre de AssertJ. EDIT: Il semble que le projet est le brassage d'une Java 8 Lambdas de soutien.Actuellement, cette bibliothèque a deux défauts :
Au moment d'écrire ces lignes, il convient de dire que cette bibliothèque est fondée sur Mockito 1.x car elle crée un simulacre de l'objet testé derrière la scène. Comme Mockito est pas encore mis à jour cette bibliothèque ne peut pas travailler avec final classes ou finale méthodes. Et même si elle était fondée sur mockito 2 dans la version actuelle, ce serait à déclarer un mondial se moquer maker (
inline-mock-maker
), peut-être pas ce que vous voulez, que ce mockmaker a différents inconvénients que l'mockmaker.Il nécessite encore un autre test de dépendance.
Ces questions ne s'appliquent pas dès lors que la bibliothèque sera de soutenir les lambdas, cependant la fonctionnalité sera dupliqué par AssertJ d'outils.
En prenant tout en compte si vous ne souhaitez pas utiliser le fourre-exception outil, je vais recommander le bon vieux chemin de la
try
-catch
bloquer, au moins jusqu'à la JDK7. Et pour JDK 8 utilisateurs, vous pouvez préférer utiliser AssertJ car il offre plus que de simplement faire valoir des exceptions.Avec le JDK8, lambdas entrer dans la scène de test, et ils l'ont prouvé à être un moyen intéressant pour faire valoir exceptionnelles comportement. AssertJ a été mis à jour pour offrir une belle API fluent pour affirmer exceptionnelles comportement.
Et un échantillon de test avec AssertJ :
Avec un près de la réécriture complète de JUnit 5, affirmations ont été l'amélioration de un peu, ils peuvent s'avérer intéressantes, comme une sortie de la boîte de façon à faire valoir correctement exception. Mais en fait, l'affirmation de l'API est encore un peu pauvre, il n'y a rien en dehors de
assertThrows
.Comme vous avez remarqué
assertEquals
est encore de retourvoid
et en tant que tel ne permet pas de chaînage des affirmations comme AssertJ.Aussi, si vous vous souvenez de conflit de nom avec
Matcher
ouAssert
être prêt à répondre à la même contradiction avecAssertions
.J'aimerais conclure qu'aujourd'hui (2017-03-03) AssertJ's la facilité d'utilisation, détectable de l'API, le rythme rapide de développement et comme un de facto test de dépendance est la meilleure solution avec JDK8 indépendamment de la structure de test (JUnit ou pas), avant Jdk devrait plutôt s'appuyer sur
try
-catch
blocs même si ils se sentir maladroit.Si je ne comprends pas vous tromper, vous besoin de quelque chose comme ceci:
mais par la désignation de l'essai "NPENotThrown" je m'attends à un test comme ceci:
Une autre approche pourrait être d'utiliser try/catch à la place. C'est un peu en désordre, mais ce que je comprends de ce test va être de courte durée, de toute façon tant que c'est pour le TDD:
EDIT: j'ai été pressé quand j'ai écrit cela. Ce que je veux dire par "ce test va être de courte durée, de toute façon tant que c'est pour le TDD' est que vous dites que vous allez écrire un peu de code pour résoudre ce test tout de suite, donc il ne sera jamais jeter un NullPointerException dans l'avenir. Alors vous pourriez aussi bien supprimer le test. Par conséquent, il n'est probablement pas la peine de dépenser beaucoup de temps à écrire un beau test (d'où ma suggestion :-))
Plus généralement:
De commencer par un test d'affirmer que (par exemple), la valeur de retour d'une méthode n'est pas la valeur null est une TDD principe, et la vérification d'une NullPointerException (NPE) est un moyen d'aller à ce sujet. Toutefois, votre code de production est probablement ne va pas avoir un flux où un NPE est levée. Vous allez vérifier la valeur null et puis faire quelque chose d'intelligent, j'imagine. Ce qui ferait de test particulier redondant à ce moment-là que ça va être de la vérification des entrées en phase nationale n'est pas jeté, alors qu'en fait, il ne peut jamais arriver. Vous pouvez le remplacer par un test qui vérifie ce qui arrive quand une valeur null est rencontrés: retourne une NullObject par exemple, ou s'il jette quelque autre type d'exception, tout ce qui est approprié.
Il n'y a évidemment pas d'obligation de vous supprimer le test redondants, mais si vous ne le faites pas, il va s'asseoir là à faire de chaque build un peu plus lent, et les responsables de chaque développeur qui lit le test à merveille; "Hmm, un NPE? Assurément, ce code ne peut pas jeter un NPE?". J'ai vu beaucoup de TDD code où les classes de test ont beaucoup de tests redondants comme ça. Si le temps le permet, il paie à l'examen de vos tests chaque tellement souvent.
De manière générale, chaque cas de test s'exécute avec une nouvelle instance paramètre une variable d'instance ne va pas aider. Donc, assurez - '
throw
variable statique dans le cas contraire.