2010-09-28 18 views
8

Nella nostra applicazione, ci aspettiamo che l'input dell'utente all'interno di un Thread come segue:La scrittura di dati System.in

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 

voglio passare questa parte nel mio test di unità in modo che possa riprendere il filo per eseguire il resto del codice. Come posso scrivere qualcosa su System.in da junit?

+1

non pensavo si potesse, ma a quanto pare è possibile secondo Giustino. Tuttavia, non sarebbe meglio refactoring il codice testato per ottenere l'inputstream inserito dall'esterno? –

+0

@Bart, se stai provando un'app che prende input da 'System.in', alla fine vorrai testare il modulo che prende i dati da' System.in'. – jjnguy

+2

@Justin Non sta testando Java e non il tuo codice? Se si immette InputStream, si sta ancora testando tutto il codice e in base a Java per fornire System.in corretto. –

risposta

20

Quello che vuoi fare è utilizzare il metodo setIn() da System. Questo ti permetterà di passare i dati in System.in da junit.

+0

Funziona quando eseguo i test JUnit singolarmente, ma quando eseguo l'intera classe il mio programma sembra bloccarsi nei punti in cui dovrebbe funzionare setIn(). Qualcun altro ha questo problema, e in tal caso qualche idea su come aggirarlo? – decal

+0

@decal il tuo problema potrebbe essere stato errato setup() & tearDown() modificando quei valori System.in() e System.out(). Ci sono altri riferimenti a quel problema altrove su SE. Se qualcun altro vede questo commento cercherò e sostituirò .. – Crowie

9

Sostituirlo per tutta la durata del test:

String data = "the text you want to send"; 
InputStream testInput = new ByteArrayInputStream(data.getBytes("UTF-8")); 
InputStream old = System.in; 
try { 
    System.setIn(testInput); 

    ... 
} finally { 
    System.setIn(old); 
} 
+0

Piccolo dettaglio: poiché il bufferedreader è costruito senza un set di caratteri, non dovresti chiamare 'getBytes()' senza un set di caratteri (o, naturalmente, aggiungere un charset per il bufferedreader)? –

5

Invece dei suggerimenti di cui sopra (Edit: ho notato che Bart ha lasciato questa idea in un commento così), vorrei suggerire facendo la classe più unità testabili rendendo la classe accetta la sorgente di input come parametro costruttore o simile (iniettare la dipendenza). Una classe non dovrebbe essere così accoppiata a System.in comunque.

Se la classe è costruito da un lettore, si può solo fare questo:

class SomeUnit { 
    private final BufferedReader br; 
    public SomeUnit(Reader r) { 
     br = new BufferedReader(r); 
    } 
    //... 
} 

//in your real code: 
SomeUnit unit = new SomeUnit(new InputStreamReader(System.in)); 

//in your JUnit test (e.g.): 
SomeUnit unit = new SomeUnit(new StringReader("here's the input\nline 2")); 
Problemi correlati