2010-01-30 4 views
24

J'écris des tests d'intégration en utilisant JUnit pour automatiser le test d'une application basée sur une console. L'application est à la maison mais cette partie n'est pas le devoir. Je veux automatiser ces tests pour être plus productif - je ne veux pas avoir à revenir en arrière et retester des parties déjà testées de l'application. (Raisons standard pour utiliser les tests unitaires)Java, Junit - Capture de l'entrée/sortie standard pour utilisation dans un test unitaire

Quoi qu'il en soit, je ne peux pas trouver ou trouver un article sur la capture de la sortie afin que je puisse faire assertEquals sur elle ni fournir une entrée automatisée. Je m'en fiche si la sortie/entrée va à la console/volet de sortie. Je n'ai besoin que d'exécuter le test et de vérifier que la sortie est ce qui est attendu compte tenu de l'entrée.

N'importe qui a un article ou un code pour vous aider.

+0

@dfa, je ne suis pas d'accord. C'est similaire en effet mais assez différent. –

+0

... accordé la réponse est la même ... –

+1

L'autre thread a maintenant une meilleure réponse. Cela implique l'utilisation de la règle de système jUnit StandardOutputStreamLog. Il existe également des règles système pour stderr et stdin. –

Répondre

38

Utilisez System.setOut() (et System.setErr()) pour rediriger la sortie vers un flux d'impression arbitraire - qui peut être celui que vous avez lu par programmation.

Par exemple:

final ByteArrayOutputStream myOut = new ByteArrayOutputStream(); 
System.setOut(new PrintStream(myOut)); 

// test stuff here... 

final String standardOutput = myOut.toString(); 
+1

Aller simplement 'PrintStream _out = System.out;' Ne fonctionnera pas? –

+0

Ce serait - c'est-à-dire que vous auriez une référence au flux de sortie existant - mais vous ne pouvez * rien * en lire car il n'y a pas de méthodes appropriées pour le faire sur l'interface générale 'PrintStream'. La technique consiste à définir la sortie sur un flux d'impression spécifique dont vous savez lire. –

7

La classe System a des méthodes setIn(), setOut() et setErr() qui vous permettent de définir l'entrée standard, sortie et flux d'erreur, par exemple à un ByteArrayOutputStream que vous pouvez inspecter à volonté.

1

Voici la solution à la place de ByteArrayOutputStream. Cela n'ajoute rien à l'idée de System.setOut. Au contraire, je veux partager l'implémentation qui est meilleure que de tout capturer dans ByteArrayOutputStream. Je préfère ne capturer que les informations sélectionnées et laisser tous les messages de journal apparaître dans la console au fur et à mesure qu'ils sont enregistrés plutôt que de tout capturer dans une balckbox (de quelle taille?) Pour un traitement ultérieur.

/** 
* Once started, std output is redirected to this thread. 
* Thread redirects all data to the former system.out and 
* captures some strings.*/ 
static abstract class OutputCaputre extends Thread { 

    // overrdie these methods for System.err 
    PrintStream getDownstream() { return System.out;} 
    void restoreDownstream() { System.setOut(downstream);} 

    // will be called for every line in the log 
    protected abstract void userFilter(String line); 

    final PrintStream downstream; 
    public final PipedInputStream pis; 
    private final PipedOutputStream pos; 
    OutputCaputre() throws IOException { 
     downstream = getDownstream(); 

     pos = new PipedOutputStream(); 
     pis = new PipedInputStream(pos); 
     System.setOut(new PrintStream(pos)); 

     start(); 
    } 

    public void run() { 
     try { 
      BufferedReader br = new BufferedReader(new InputStreamReader(pis)); 

      // once output is resotred, we must terminate 
      while (true) { 
       String line = br.readLine(); 
       if (line == null) { 
        return; 
       } 
       downstream.println(line); 
       userFilter(line); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void terminate() throws InterruptedException, IOException { 
     restoreDownstream(); // switch back to std 
     pos.close(); // there will be no more data - signal that 
     join(); // and wait until capture completes 
    } 
}; 

Voici un exemple d'utilisation de la classe:

OutputCaputre outputCapture = new OutputCaputre() { 
    protected void userFilter(String line) { 
     downstream.println("Capture: " + line); 
    }  
}; 
System.out.println("do you see me captured?"); 
// here is your test  
outputCapture.terminate(); // finally, stop capturing 
Questions connexes