Java: Comment les méthodes de test que le Système d'appel.exit()?
J'ai quelques méthodes qui doivent appeler System.exit()
sur certains intrants. Malheureusement, le test de ces cas, les causes de JUnit pour mettre fin à! Mettre les appels de méthode dans un nouveau Thread ne semble pas aider, car System.exit()
met fin à la JVM, et pas seulement le thread courant. Existe-il des modèles communs pour faire face à cela? Par exemple, je peux substituer un stub pour System.exit()
?
[MODIFIER] La classe en question est en fait un outil de ligne de commande qui je suis tenté de tester à l'intérieur de JUnit. Peut-être JUnit est tout simplement pas le bon outil pour le travail? Des Suggestions pour des tests de régression outils sont les bienvenus (de préférence quelque chose qui s'intègre bien avec JUnit et EclEmma).
- Je suis curieux de savoir pourquoi une fonction serait jamais appel Système.exit()...
- Si vous appelez une fonction qui quitte l'application. Par exemple, si l'utilisateur tente d'effectuer une tâche qu'ils ne sont pas autorisés à effectuer de plus de x fois dans une ligne, vous avez la force de les sortir de l'application.
- Je continue de penser que, dans ce cas, il devrait y avoir une plus belle façon de revenir à partir de l'application plutôt que de Système.exit().
- Si vous faites des tests de main(), alors il est parfaitement logique de Système d'appel.exit(). Nous avons une exigence que sur l'erreur d'un processus de traitement par lots, sortir avec 1 et sur le succès de la sortie à 0.
- Je suis en désaccord avec tout le monde qui dit
System.exit()
est mauvais - votre programme doit échouer rapidement. Lancer une exception purement prolonge une application dans un état non valide dans les situations où un développeur veut quitter et de se donner de faux messages d'erreur.
Vous devez vous connecter pour publier un commentaire.
En effet, Derkeiler.com suggère:
System.exit()
?System.exit()
pour réellement sortir de la JVM:Mise À Jour De Décembre 2012:
Va propose dans les commentaires à l'aide de Système de Règles, une collection de JUnit(4.9+) règles pour la vérification du code qui utilise
java.lang.System
.Il a d'abord été mentionné par Stefan Birkner dans sa réponse en décembre 2011.
Par exemple:
System.getProperty("gnu.posixly_correct", null)
(Getopt.java de ligne, 615). Cela provoque une exception de sécurité pour être jeté à chaque fois que leNoExitSecurityManager
est installé. J'ai aussi essayé la plus élaboréeNoExitSecurityManager
de la SystemRules bibliothèque mentionné dans une autre réponse, mais il jette aussi l'exception.System.exit
chaque fois qu'une ligne de commande non valide argument est fourni.La bibliothèque Système De Règles a un JUnit règle appelée ExpectedSystemExit. Avec cette règle, vous êtes en mesure de tester le code, que les appels Système.la sortie(...):
Divulgation complète: je suis l'auteur de la bibliothèque.
ExpectedSystemRule
est agréable, bien sûr; le problème est qu'il nécessite une 3e partie de la bibliothèque qui fournit très peu de monde réel utilité, et est JUnit spécifiques.ExpectedSystemExit
ne fonctionne pas correctement en multi-thread tests.exit.checkAssertionAfterwards()
.junit-vintage-engine
etjunit:junit:4.12
et les choses en général, maisSystem.exit
dans la donné naissance à la JVM ne semble pas être ignoré. junit.org/junit5/docs/current/user-guide/...Vous fait peut simulé ou stub les
System.exit
méthode, dans un test JUnit.Par exemple, à l'aide de JMockit vous pouvez écrire (il y a d'autres façons):
EDIT: test de remplacement (en utilisant les dernières JMockit API) qui ne permettent pas de code à exécuter après un appel à
System.exit(n)
:exit
appel (non pas que c'était vraiment un problème, OMI).Runtime
peut se moque de lui, mais ne l'arrête pasSystem.exit
au moins dans mon scénario de l'exécution des Tests dans Gradle.java.lang.System
ne peut plus être moqué, mais il peut encore être faux (avec unMockUp
).Comment injecter un "ExitManager" dans cette Méthodes:
La production de code utilise la ExitManagerImpl et le code de test utilise ExitManagerMock et peut vérifier si exit() a été appelé, et avec lequel le code de sortie.
Un truc que nous avons utilisé dans notre base de code était d'avoir l'appel Système.exit() être encapsulé dans un Exécutable impl, que la méthode en question est utilisé par défaut. À l'unité de test, nous avons mis une autre maquette Praticable. Quelque chose comme ceci:
...et la méthode de test JUnit...
J'aime certaines des réponses déjà données, mais je voulais montrer une autre technique qui est souvent utile lors de la prise en héritage code sous test. Compte tenu de code comme:
Vous pouvez faire un coffre-fort refactoring pour créer une méthode qui encapsule le Système.la sortie de l'appel:
Ensuite, vous pouvez créer un faux pour ton test qui remplace sortie:
C'est une technique générique pour la substitution de comportement pour les cas de test, et je l'utilise tout le temps lors d'un refactoring du code legacy. Il habituellement pas où je vais laisser chose, mais une étape intermédiaire pour obtenir le code existant sous test.
Créer une maquette en mesure de classe qui encapsule le Système.exit()
Je suis d'accord avec EricSchaefer. Mais si vous utilisez un bon moqueur cadre comme Mockito une simple classe de béton est suffisant, pas besoin d'une interface et des deux implémentations.
Essai de l'arrêt de l'exécution sur le Système.exit()
Problème:
Un moqué
Sytem.exit()
de ne pas interrompre l'exécution. C'est mauvais si vous voulez tester quething2
n'est pas exécutée.Solution:
Vous devriez refactoriser ce code comme suggéré par martin:
Et ne
System.exit(status)
dans la fonction appelante. Cela vous oblige à avoir tous vosSystem.exit()
s en un seul endroit dans ou à proximité demain()
. C'est plus propre que de faire appelSystem.exit()
profondément à l'intérieur de votre logique.Code
Wrapper:
Principal:
Test:
Un rapide coup d'oeil à l'api, montre que le Système.la sortie peut lever une exception de l'esp. si un securitymanager interdit l'arrêt de la vm. Peut-être qu'une solution serait d'installer un tel gestionnaire.
Vous pouvez utiliser le java SecurityManager pour empêcher le thread en cours d'arrêt de la machine virtuelle Java. Le code suivant devrait faire ce que vous voulez:
Pour VonC, en réponse à exécuter sur JUnit 4, j'ai modifié le code comme suit
Il existe des environnements où l'renvoyé le code de sortie est utilisé par le programme appelant (comme ERRORLEVEL dans MS Lot). Nous avons des tests sur les principales méthodes de le faire dans notre code, et notre approche a été d'utiliser un SecurityManager remplacer celle utilisée dans d'autres tests ici.
La nuit dernière j'ai mis en place un petit POT en utilisant Junit @Règle des annotations pour masquer le gestionnaire de sécurité code, ainsi que d'ajouter des attentes fondées sur le rendement attendu de code. http://code.google.com/p/junitsystemrules/
Vous pouvez tester le Système.sortie(..) avec le remplacement d'Exécution de l'instance.
E. g. avec TestNG + Mockito:
Système D'Appel.exit() est une mauvaise pratique, sauf si c'est fait à l'intérieur d'une main(). Ces méthodes devraient être lancer une exception qui, en fin de compte, est capturé par votre main(), qui appelle ensuite le Système.sortie avec le code approprié.
Utilisation
Runtime.exec(String command)
de démarrage de la JVM dans un processus séparé.Il y a un petit problème avec le
SecurityManager
solution. Certaines méthodes, telles queJFrame.exitOnClose
, aussi appelSecurityManager.checkExit
. Dans mon application, je ne voulais pas que l'appel à l'échec, j'ai donc utilisé