JUnit test pour le Système.out.println()
J'ai besoin d'écrire JUnit tests pour une application ancienne qui est mal conçu et écrit beaucoup de messages d'erreur sur la sortie standard. Lorsque le getResponse(String request)
méthode fonctionne correctement, il 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 XML mal formé ou ne comprend pas la demande, il renvoie null
et écrit des trucs sur la sortie standard.
Est-il possible d'affirmer 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());
- Liés à, mais pas un doublon de stackoverflow.com/questions/3381801/...
Vous devez vous connecter pour publier un commentaire.
à l'aide de ByteArrayOutputStream et du Système.setXXX est simple:
test de l'échantillon de cas:
J'ai utilisé ce code pour tester l'option de ligne de commande (affirmant que la version sorties de la chaîne de version, etc etc)
Edit:
Les versions antérieures de cette réponse appelle
System.setOut(null)
après les tests; C'est la cause de NullPointerExceptions commentateurs se réfèrent.NullPointerException
dans d'autres tests après la définition d'une erreur nulle flux comme suggéré ci-dessus (dansjava.io.writer(Object)
, appelée en interne par un validateur XML). Je dirais plutôt économiser de l'original dans un domaine:oldStdErr = System.err
et la restauration de cette dans le@After
méthode.@BeforeAll
et@AfterAll
pour JUnit5.Je sais que c'est un vieux thread, mais il y a une belle bibliothèque pour ce faire:
Système De Règles
Exemple de la doc:
Il vous permettra également de piège
System.exit(-1)
et d'autres choses qu'un outil de ligne de commande devrait être testée pour.Vous pouvez configurer le Système.hors flux d'impression via sera() (et pour
in
eterr
). Pouvez-vous rediriger un flux d'impression qui enregistre sur une chaîne, puis vérifiez que ? Qui semble être le plus simple mécanisme.(Je préconiserais, à un certain stade, de le convertir à l'application de certaines de journalisation - mais je soupçonne que vous êtes déjà au courant de cela!)
Au lieu de rediriger
System.out
, je refactoriser la classe qui l'utiliseSystem.out.println()
par le passage d'unPrintStream
tant que collaborateur, puis à l'aide deSystem.out
de la production et une Test Spy dans le test. C'est, utiliser l'Injection de Dépendance pour éliminer l'utilisation directe du flux de sortie standard.Dans La Production
Dans le Test
Discussion
De cette façon, la classe sous test devient testable par un simple, sans avoir besoin de indirect de la redirection de la sortie standard ou obscur interception avec un système de règle.
ConsoleWriter
est le sujet de test,Légèrement hors sujet, mais dans le cas où certaines personnes (comme moi, quand j'ai d'abord trouvé ce fil) pourrait être intéressé par la capture de la sortie du journal via SLF4J, communes-test's JUnit
@Rule
pourraient vous aider:Avertissement:
log4j
,log4j2
etlogback
sont disponibles pour le moment, mais je suis heureux d'ajouter plus.@dfa réponse est grande, donc je l'ai pris un peu plus loin pour le rendre possible de faire le test des blocs de sortie.
J'ai d'abord créé
TestHelper
avec une méthodecaptureOutput
qui accepte les annoymous classeCaptureTest
. Le captureOutput méthode effectue le travail de définition et de démolir les flux de sortie. Lors de la mise en œuvre deCaptureOutput
'stest
méthode est appelée, elle a accès à la sortie de générer pour le bloc d'essai.Source pour TestHelper:
Noter que TestHelper et CaptureTest sont définies dans le même fichier.
Puis dans votre test, vous pouvez importer de la statique captureOutput. Voici un exemple d'utilisation de JUnit:
Si vous étiez à l'aide de Printemps de Démarrage (vous avez mentionné que vous travaillez avec une ancienne application, de sorte que vous ne sont probablement pas, mais il pourrait être utile à d'autres), alors vous pouvez utiliser org.springframework.de démarrage.test.la règle.OutputCapture de la manière suivante:
Basé sur @dfa réponse et une autre réponse qui montre comment le Système de test.dans, je voudrais partager ma solution pour donner une entrée à un programme et de tester sa sortie.
Comme une référence, je utiliser JUnit 4.12.
Disons que nous avons de ce programme qui reprend simplement l'entrée à la sortie:
Pour le tester, nous pouvons utiliser la classe suivante:
Je ne vais pas expliquer en grande partie, parce que je crois que le code est lisible et j'ai cité mes sources.
Quand JUnit s'exécute
testCase1()
, il va appeler les méthodes d'assistance dans l'ordre où ils apparaissent:setUpOutput()
, en raison de la@Before
annotationprovideInput(String data)
, appelé à partir detestCase1()
getOutput()
, appelé à partir detestCase1()
restoreSystemInputOutput()
, en raison de la@After
annotationJe n'ai pas fait de test
System.err
parce que je n'en avais pas besoin, mais il devrait être facile à mettre en œuvre, similaire au test deSystem.out
.Vous ne voulez pas rediriger le système.hors stream parce que les redirections pour l'ENSEMBLE de la JVM. Rien d'autre en cours d'exécution sur la JVM peut obtenir foiré. Il y a de meilleures façons de test d'entrée/sortie. Regardez dans les stubs/simulacres.
Plein JUnit 5 par exemple pour tester
System.out
(remplacer lors de la partie):Vous ne pouvez pas imprimer directement en utilisant système.out.println ou à l'aide de enregistreur api tout en utilisant JUnit. Mais si vous voulez vérifier toutes les valeurs, alors vous pouvez simplement utiliser
Qu'il va jeter ci-dessous erreur d'assertion:
Votre valeur doit être 21.92, Maintenant, si vous voulez tester l'utilisation de cette valeur comme ci-dessous votre cas de test va passer.
pour
pour tre
@Rule
, plutôt que de le faire en ligne dans votre test. Notamment, si votre assertion échoue à la deuxièmeSystem.setOut/Err
appel pas être atteint.