J'ai besoin d'écrire des tests JUnit pour une ancienne application mal conçue et écrit beaucoup de messages d'erreur sur la sortie standard. Lorsque la getResponse(String request)
méthode se comporte correctement, elle renvoie une réponse XML:
@BeforeClass
public static void setUpClass() throws Exception {
Properties queries = loadPropertiesFile("requests.properties");
Properties responses = loadPropertiesFile("responses.properties");
instance = new ResponseGenerator(queries, responses);
}
@Test
public void testGetResponse() {
String request = "<some>request</some>";
String expResult = "<some>response</some>";
String result = instance.getResponse(request);
assertEquals(expResult, result);
}
Mais quand il obtient du XML mal formé ou ne comprend pas la demande, il retourne null
et écrit des trucs sur la sortie standard.
Existe-t-il un moyen d'affirmer la sortie de la console dans JUnit? Pour attraper des cas comme:
System.out.println("match found: " + strExpr);
System.out.println("xml not well formed: " + e.getMessage());
Réponses:
l'utilisation de ByteArrayOutputStream et System.setXXX est simple:
exemples de cas de test:
J'ai utilisé ce code pour tester l'option de ligne de commande (en affirmant que -version génère la chaîne de version, etc., etc.)
Edit: versions antérieures de cette réponse appelées
System.setOut(null)
après les tests; C'est la cause des commentaires de NullPointerExceptions.la source
NullPointerException
dans d'autres tests après avoir défini un flux d'erreur nul comme suggéré ci-dessus (dansjava.io.writer(Object)
, appelé en interne par un validateur XML). Je suggère plutôt de sauvegarder l'original dans un champ:oldStdErr = System.err
et de le restaurer dans la@After
méthode.Je sais que c'est un vieux fil, mais il y a une belle bibliothèque pour le faire:
Règles système
Exemple de la documentation:
Il vous permettra également d'intercepter
System.exit(-1)
et d'autres choses pour lesquelles un outil de ligne de commande devrait être testé.la source
Au lieu de rediriger
System.out
, je refactoriserais la classe qui utiliseSystem.out.println()
en passant aPrintStream
comme collaborateur puis en utilisantSystem.out
en production et un Test Spy dans le test. Autrement dit, utilisez l'injection de dépendance pour éliminer l'utilisation directe du flux de sortie standard.En production
Dans le test
Discussion
De cette façon, la classe testée peut être testée par une simple refactorisation, sans avoir besoin de redirection indirecte de la sortie standard ou d'interception obscure avec une règle système.
la source
ConsoleWriter
c'est le sujet du test,Vous pouvez définir le flux d'impression System.out via setOut () (et pour
in
eterr
). Pouvez-vous rediriger cela vers un flux d'impression qui enregistre dans une chaîne, puis inspecter cela? Cela semblerait être le mécanisme le plus simple.(Je recommanderais, à un moment donné, de convertir l'application en un cadre de journalisation - mais je soupçonne que vous en êtes déjà conscient!)
la source
Un peu hors sujet, mais dans le cas où certaines personnes (comme moi, quand je trouvé ce fil) pourraient être intéressés à capturer la sortie du journal via SLF4J, commons-test de » JUnit
@Rule
pourrait l'aide:Clause de non - responsabilité :
log4j
,log4j2
etlogback
sont disponibles pour le moment, mais je suis heureux d'en ajouter d'autres.la source
La réponse @dfa est excellente, j'ai donc fait un pas de plus pour permettre de tester des blocs de sortie.
J'ai d'abord créé
TestHelper
avec une méthodecaptureOutput
qui accepte la classe ennuyeuseCaptureTest
. La méthode captureOutput effectue le travail de définition et de suppression des flux de sortie. Lorsque l'implémentation deCaptureOutput
latest
méthode de est appelée, elle a accès à la sortie générée pour le bloc de test.Source pour TestHelper:
Notez que TestHelper et CaptureTest sont définis dans le même fichier.
Ensuite, dans votre test, vous pouvez importer le captureOutput statique. Voici un exemple utilisant JUnit:
la source
Si vous utilisiez Spring Boot (vous avez mentionné que vous travaillez avec une ancienne application, vous ne l'êtes probablement pas, mais elle pourrait être utile à d'autres), alors vous pourriez utiliser org.springframework.boot.test.rule.OutputCapture De la manière suivante:
la source
Sur la base de la réponse de @ dfa et d' une autre réponse qui montre comment tester System.in , je voudrais partager ma solution pour donner une entrée à un programme et tester sa sortie.
Comme référence, j'utilise JUnit 4.12.
Disons que nous avons ce programme qui réplique simplement l'entrée en sortie:
Pour le tester, nous pouvons utiliser la classe suivante:
Je n'expliquerai pas grand-chose, car je pense que le code est lisible et j'ai cité mes sources.
Lorsque JUnit s'exécute
testCase1()
, il va appeler les méthodes d'assistance dans l'ordre où elles apparaissent:setUpOutput()
, à cause de l'@Before
annotationprovideInput(String data)
, appelé depuistestCase1()
getOutput()
, appelé depuistestCase1()
restoreSystemInputOutput()
, à cause de l'@After
annotationJe n'ai pas testé
System.err
parce que je n'en avais pas besoin, mais il devrait être facile à implémenter, similaire aux testsSystem.out
.la source
Vous ne voulez pas rediriger le flux system.out car cela redirige pour la JVM ENTIÈRE. Tout autre élément exécuté sur la JVM peut être gâché. Il existe de meilleures façons de tester les entrées / sorties. Examinez les moignons / moqueries.
la source
Exemple complet de JUnit 5 à tester
System.out
(remplacez la partie quand):la source
Vous ne pouvez pas imprimer directement à l'aide de system.out.println ou à l'aide de l' API de l'enregistreur lorsque vous utilisez JUnit . Mais si vous voulez vérifier des valeurs, vous pouvez simplement utiliser
Il renverra l'erreur d'assertion ci-dessous:
Votre valeur devrait être 21,92, maintenant si vous testez en utilisant cette valeur comme ci-dessous, votre cas de test passera.
la source
pour sortir
pour erreur
la source
@Rule
, plutôt que de le faire en ligne dans votre test. Notamment, si votre assertion échoue, le deuxièmeSystem.setOut/Err
appel ne sera pas atteint.