JUnit test grâce à la simulation de la saisie de l'utilisateur
Je suis en train de créer des tests JUnit pour une méthode qui nécessite la saisie de l'utilisateur. La méthode de test ressemble un peu à la méthode suivante:
public static int testUserInput() {
Scanner keyboard = new Scanner(System.in);
System.out.println("Give a number between 1 and 10");
int input = keyboard.nextInt();
while (input < 1 || input > 10) {
System.out.println("Wrong number, try again.");
input = keyboard.nextInt();
}
return input;
}
Est-il possible de transmettre automatiquement le programme d'un int au lieu de moi ou de quelqu'un d'autre de le faire manuellement dans le test JUnit méthode? De simuler la saisie de l'utilisateur?
Merci d'avance.
- De quoi êtes-vous tests, exactement? Scanner? Une méthode de test doivent généralement faire valoir quelque chose d'utile.
- Vous ne devriez pas avoir à tester Java de la classe Scanner. Vous pouvez manuellement régler votre entrée et simplement tester votre propre logique. d'entrée int = -1 ou 5 ou 11 couvrira votre logique
- Six ans plus tard... et c'est toujours une bonne question. Pas moins parce que quand on commence à développer une app, vous pouvez généralement veulent pas avoir toutes les cloches et de sifflets de JavaFX, mais au lieu de commencer à utiliser l'humble ligne de commande pour un peu très de base de l'interaction. Dommage que JUnit ne font de ce fait un peu plus facile. Pour moi, Omar Elshal la réponse est très agréable, avec un minimum de "artificiel" ou "déformées" application de codage en cause...
Vous devez vous connecter pour publier un commentaire.
Vous pouvez remplacer Système.dans votre propre flux par l'appel Système.setIn(InputStream in).
Flux d'entrée peut être tableau d'octets:
Approche différente peut être rendre cette méthode plus testable en passant comme paramètres:
\n
mais ce n'est pas faire une différenceByteArrayInputStream in = new ByteArrayInputStream(("1" + System.lineSeparator() + "2").getBytes());
pour obtenir des entrées multiples pour les différentskeyboard.nextLine()
appels.De tester votre code, vous devez créer un wrapper pour le système d'entrée/sortie de fonctions. Vous pouvez faire cela en utilisant l'injection de dépendance, nous donnant une classe qui peut demander une nouvelle entiers:
Ensuite, vous pouvez créer des tests de votre fonction, à l'aide d'une maquette cadre (j'utilise Mockito):
Puis rédigez votre fonction qui passe les tests. La fonction est beaucoup plus propre comme vous pouvez retirer la demande/obtenir de l'entier de la duplication et le système réel les appels sont encapsulées.
Cela peut sembler excessif pour votre petit exemple, mais si vous créez une application plus large en développement, comme cela peut de paiement plutôt rapidement.
Une voie commune pour tester un code similaire serait d'extraire une méthode qui prend un Scanner et d'un PrintWriter, semblable à cette StackOverflow répondre, et test:
Ne remarque que vous ne serez pas en mesure de lire votre sortie jusqu'à la fin, et vous aurez à spécifier toutes de votre entrée à l'avant:
Bien sûr, plutôt que de créer une surcharge de la méthode, vous pouvez aussi garder le "scanner" et "sortie" comme champs mutables dans votre système sous test. J'ai une tendance à garder les classes comme des apatrides que possible, mais ce n'est pas une très grande concession si c'est important pour vous ou vos collègues de travail/de l'instructeur.
Vous pouvez aussi choisir de mettre votre code de test dans le même package Java comme le code sous test (même si c'est dans un autre dossier source), ce qui vous permet de vous détendre de la visibilité des deux paramètres de surcharge à colis-privé.
Vous pourriez commencer par l'extraction de la logique qui récupère le numéro à partir du clavier dans sa propre méthode. Ensuite, vous pouvez tester la logique de validation, sans vous soucier du clavier. Afin de tester le clavier.nextInt() appel vous pouvez envisager d'utiliser un objet fantaisie.
J'ai réussi à trouver une façon plus simple. Cependant, vous devez utiliser une bibliothèque externe Système.les règles Par @Stefan Birkner
J'ai juste pris l'exemple fourni là, je pense qu'il ne pourrait pas avoir obtenu plus simple 🙂
Le problème, toutefois, dans mon cas, mon deuxième entrée des espaces et de ce fait, l'ensemble du flux d'entrée nul !
inputEntry = scanner.nextLine();
lorsqu'il est utilisé avecSystem.in
toujours attendre pour l'utilisateur (et acceptera une ligne vide comme un videString
)... alors que lorsque les lignes d'approvisionnement à l'aide desystemInMock.provideLines()
cela permettra de jeterNoSuchElementException
lorsque les lignes se lancer. Ce qui rend vraiment facile de ne pas "fausser" le code de l'application trop à répondre au test.systemInMock.provideLines("1", "2");
2. En Utilisant Le Système.setIn sans bibliothèques externes:String data2 = "1 2";
System.setIn(new ByteArrayInputStream(data2.getBytes()));
Que j'ai trouvé utile de créer une interface qui définit les méthodes similaire à java.io.Console et ensuite l'utiliser pour la lecture ou l'écriture pour le Système.out. La mise en œuvre réelle de déléguer à Système.console() lors de votre JUnit version peut être un objet fantaisie avec des conserves d'entrée et de réponses attendues.
Par exemple, la construction d'un MockConsole que le contenu de la conserve l'entrée de l'utilisateur. La simulation de la mise en œuvre de la pop une chaîne d'entrée de la liste à chaque fois readLine a été appelé. Il serait également recueillir la totalité de la production écrite à une liste de réponses. À la fin de l'essai, si tout s'est bien passé, puis l'ensemble de votre entrée aurait été lu et vous pouvez faire valoir sur la sortie.
J'ai réglé le problème sur lire sur stdin pour simuler une console...
Mes problèmes est que je voudrais essayer d'écrire dans JUnit test de la console pour créer un objet...
Le problème, c'est comme tout ce que tu dis : Comment puis-je écrire dans le Stdin de test JUnit?
Puis au collège j'en apprends sur les redirections comme tu le dis Système.setIn(InputStream) changer le stdin filedescriptor et vous pouvez écrire à puis...
Mais il y a encore un problème à résoudre... le test JUnit bloquer en attente de lecture à partir de votre nouveau InputStream, de sorte que vous besoin de créer un thread pour lire à partir de l'InputStream et de test JUnit Fil écrire dans la nouvelle Stdin... d'Abord, vous devez écrire dans le Stdin parce que si vous écrivez, plus tard, de la création du Thread de lecture à partir de stdin vous aurez probablement des Conditions de course... vous pouvez écrire dans le InputStream avant de lire ou vous pouvez lire à partir de InputStream avant d'écrire...
C'est mon code, mon anglais compétence est mauvais, je l'espère, tout ce que vous pouvez comprendre le problème et la solution pour simuler écrire dans stdin de test JUnit.