2013-06-13 7 views
9

Vedo un sacco di domande su come fare in modo che Intellij si interrompa sulle eccezioni. Sto provando a fare qualcosa di diverso: voglio lanciare un'eccezione a un punto di interruzione in modo che possa vedere cosa accadrà se si verificasse un'eccezione a quel codice.In Intellij, come posso generare un'eccezione in corrispondenza di un punto di interruzione?

Ho trovato dei modi per forzare questo. Ad esempio, se ho una variabile denominata willBeUsed, posso raggiungere un punto di interruzione e aggiungere un orologio che dice willBeUsed = null. Ciò attiverà una NullPointerException alla fine.

Ma io sono in una situazione in cui voglio lanciare un IOException per vedere cosa succede. Non c'è modo di ingannare il mio codice nel farlo. Quando aggiungo un orologio che dice throw new IOException() mi dà un errore che dice "token imprevisti".

Come un aggiramento, posso modificare il codice per lanciare l'eccezione e ridistribuire. Ma mi chiedo se c'è un modo per farlo nel debugger senza modificare il codice sorgente.

+3

E 'improbabile che ci sia un modo per fare quello che stai chiedendo. Suggerirei di esaminare un design diverso che faciliti più facilmente questo tipo di test, ad esempio [dependency injection] (http://en.wikipedia.org/wiki/Dependency_injection). –

+1

@RobI L'iniezione di dipendenza è buona. Non vedo come mi aiuti qui. Puoi elaborare? –

+0

Breve idea: crea un'interfaccia per fare ciò che stai facendo nel blocco di codice che a volte solleva un'eccezione (ad esempio, 'IODoer' con il metodo' do() '). La vostra vera implementazione è in una classe concreta 'IODoerImpl', con tutto il codice reale, ma avete un'altra classe' 'TestIODoer', che solleva un'eccezione ogni volta che chiamate il metodo' do() ', o ogni altra volta, o ogni volta che ... Normalmente il tuo programma usa l'implementazione reale, ma durante i test puoi invece inserire questa classe di test. –

risposta

6

Come su come piazzare la dichiarazione throw in un blocco if, e solo cambiare la condizione, per es .:

boolean shouldThrowException = false; 
// .... 
if (shouldThrowException) //place breakpoint here 
{ 
    throw new IOException(); 
} 

Quando si preme il punto di interruzione, modificare il valore della shouldThrowException su true.

+0

Ho già dato questo come soluzione alla mia domanda. Ma se è l'unico modo, immagino che sia l'unico modo. –

+0

Mi dispiace, devo averlo perso nella tua domanda, mi dispiace di non essere stato troppo utile .. – MByD

1

Non riesco a vedere come questo può essere fatto. Ho provato due approcci (forse le mie idee porteranno ad altre idee

1) Ho provato ad usare il debugger "log valutato espressione" a throw new IOException() ma tutto ciò che ottengo è un messaggio che IDEA non è stato in grado di valutare l'espressione .

2) Ho anche provato a impostare un punto di interruzione e quando si è fermato apro la finestra di dialogo "Valuta espressione" per lanciare una nuova eccezione ma non ha funzionato neanche.

Non penso che il debugger possa generare eccezioni. @ La soluzione di Binyamin funzionerà ma l'hai già menzionata nella tua domanda. Posso solo aggiungere che in IDEA è possibile deselezionare la casella "sospendi" e inserire shouldThrowException = true nella casella "espressione valutata log". Ciò farà sì che il debugger modifichi semplicemente il valore (e lo registri) ma non si fermi, il che è ottimo nel codice che ha molti thread simultanei.

1

Non so se l'hai provato, ma potresti forse creare un metodo statico che solleva solo IOException e quindi chiama questo metodo inviando Evaluate Expression.

codice di esempio semplice:

package com.stackoverflow; 

import java.io.IOException; 

public class Main { 
    public static void main(String[] args) { 

     doStuff(); 
    } 

    private static void throwException() throws IOException { 
     throw new IOException(); 
    } 

    private static void doStuff() { 
     System.out.println("doStuff"); 
    } 
} 

Impostare un punto di interruzione sulla linea System.out.println:

enter image description here

visualizzare la finestra Evaluate Expression... e chiamare il metodo throwException (valutare) e poi ti ottenere una traccia dello stack dall'interno doStuff:

enter image description here

L'eccezione sarà ovviamente in throwException ma si vede anche l'intero stack di chiamate.

+0

Sì, funzionerebbe. Ma dovrei ancora ridistribuire. Ma, quello che sarebbe bello è metterlo in una biblioteca e poi potrei chiamarlo ogni volta che ho bisogno di qualsiasi progetto. In questo modo non avrei bisogno di modificare alcun file sorgente nel progetto principale o ridistribuire. Posso usare un ambito Maven in modo che non venga distribuito quando pacchetto. –

+0

@tieTYT Sì, quello era esattamente il mio pensiero. – maba

+0

Ho provato questo e l'uscita della console non mostra un'eccezione in esso. Penso che valuti l'eccezione nella sua stessa istanza in modo che non influenzi il thread principale. –

1

C'è un altro modo in cui puoi usufruire di JVM HotSwapping.

Supponiamo che stiate distribuendo il codice su qualche server. Quindi, quando avvii l'applicazione, assicurati di attivare il debug remoto (che penso si abbia dal momento che si sta eseguendo il debug e si sta parlando di distribuzione). In caso contrario, funzionerà in modo uniforme nel debugger locale.

Ora ho due classi, Principale e Altro.

package com.stackoverflow; 

import java.io.IOException; 

public class Main { 
    public static void main(String[] args) throws IOException { 
     doStuff(); 
    } 

    private static void doStuff() throws IOException { 
     System.out.println("doStuff"); 
     Other.otherStuff(); 
    } 

    public static void throwException() throws IOException { 
     throw new IOException(); 
    } 
} 


package com.stackoverflow; 

import java.io.File; 
import java.io.IOException; 

public class Other { 
    public static void otherStuff() throws IOException { 
     File file = new File("Some_File.txt"); 
     file.createNewFile(); 
    } 
} 

Il throwException() potrebbe assumere qualsiasi posizione purché sia ​​"globalmente" disponibili, in qualche classe util per esempio. Ora è appena inserito nella mia classe principale per comodità.

Ora possiamo avere un punto di interruzione impostato nel nostro metodo doStuff() e, mentre si terrà lì siamo in grado di modificare il codice nel metodo otherStuff() in modo che chiami il nostro metodo statico throwException().

public static void otherStuff() throws IOException { 
    Main.throwException(); 
    File file = new File("Some_File.txt"); 
    file.createNewFile(); 
} 

dobbiamo chiamare un metodo invece di invocare throw new IOException() perché altrimenti avremo un errore con Unreachable statement.

Poi possiamo premere Ctrl + Maiusc + F9 ricompilare il altra classe. Ora sarà HotSwapped (una finestra di dialogo chiederà se vuoi davvero farlo).

Quindi premere Continua e verrà generata l'eccezione.

Il codice può quindi essere ripristinato allo stato normale.

La cosa buona è che la classe ricompilata sarà anche scambiata a caldo "via cavo" con la macchina remota.

L'importante è che il codice da ricompilare sia in un'altra classe. La stessa classe in cui si ha il punto di interruzione non verrà ricaricata correttamente.

Come un aggiramento, posso modificare il codice per lanciare l'eccezione e ridistribuire. Ma mi chiedo se c'è un modo per farlo nel debugger senza modificare il codice sorgente.

Si modifica il codice ma solo nel momento in cui si desidera, nel debugger. È quindi possibile ripristinare la piccola modifica e ricompilare a caldo il vecchio codice.

Spero che tu abbia ottenuto l'idea (nessun gioco di parole).

Posso aggiungere schermate se lo si desidera.

+1

OK, potrebbe funzionare. Nella mia esperienza HotSwapping funziona come il 30% delle volte, ma potrebbe andare bene. Grazie –

+1

@tieTYT Spero che funzioni per oltre il 30% delle volte. Sono fuori di idee ora, questo è stato il meglio che ho potuto inventare :-) – maba

1

Penso che non sia disponibile (fino al 2018.1) fare senza modifiche nel codice.

È possibile visualizzare il problema JetBrains: IDEA-148408. È richiesta l'aggiunta di questa funzione a IntelliJ IDEA.

UPDATE: Dal 2018,1 versione è disponibile

Problemi correlati