Penso che questa domanda abbia bisogno di una risposta aggiornata, poiché la maggior parte delle risposte qui sono abbastanza obsolete.
primo luogo alla domanda del PO:
penso che la sua abbastanza ben accettato che l'introduzione del concetto di "excepetion previsto" in JUnit è stata una mossa sbagliata, dal momento che tale eccezione potrebbe essere sollevata da nessuna parte, e passerà il test. Funziona se si lanciano (e si asseriscono su) eccezioni molto specifiche del dominio, ma lancio solo quei tipi di eccezioni quando sto lavorando su un codice che deve essere assolutamente immacolato, - la maggior parte di APIS semplicemente lancia le eccezioni incorporate come IllegalArgumentException
oppure IllegalStateException
. Se due chiamate effettuate potrebbero potenzialmente lanciare queste eccezioni, l'annotazione @ExpectedException
eseguirà il test di green-bar anche se è la riga sbagliata che genera l'eccezione!
Per questa situazione ho scritto una classe che sono sicuro che molti altri hanno scritto qui, questo è un metodo assertThrows
:
public class Exceptions {
private Exceptions(){}
public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){
try{
actionThatShouldThrow.run();
fail("expected action to throw " + expectedException.getSimpleName() + " but it did not.");
}
catch(Exception e){
if (! expectedException.isInstance(e)) {
throw e;
}
}
}
}
questo metodo restituisce semplicemente se viene generata l'eccezione, che consente di fare ulteriori affermazioni/verifiche nel test.
con la sintassi java 8 il tuo test sembra davvero bello.Qui di seguito è uno dei test più semplici sul nostro modello che utilizza il metodo:
@Test
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() {
//setup
AxisRange range = new AxisRange(0,100);
//act
Runnable act =() -> range.setLowerBound(200);
//assert
assertThrows(IllegalArgumentException.class, act);
}
questi test sono un po 'traballante, perché "l'atto" passo in realtà non esegue alcuna azione, ma penso che il significato è ancora abbastanza chiaro.
c'è anche una piccola libreria su Maven chiamata catch-exception che utilizza la sintassi stile mockito per verificare che le eccezioni vengano generate. Sembra carino, ma non sono un fan dei proxy dinamici. Detto questo, c'è sintassi è così liscia rimane allettante:
// given: an empty list
List myList = new ArrayList();
// when: we try to get the first element of the list
// then: catch the exception if any is thrown
catchException(myList).get(1);
// then: we expect an IndexOutOfBoundsException
assert caughtException() instanceof IndexOutOfBoundsException;
Infine, per la situazione che ho incontrato per arrivare a questa discussione, c'è un modo per ignorare test se qualche conidition è soddisfatta.
In questo momento sto lavorando per ottenere alcune DLL chiamate tramite una libreria java nativa di libreria-caricamento chiamata JNA, ma il nostro server di build è in ubuntu. Mi piace provare a guidare questo tipo di sviluppo con i test di JUnit - anche se a questo punto sono lontani dalle "unità "--. Quello che voglio fare è eseguire il test se sono su una macchina locale, ma ignoro il test se siamo su ubuntu. JUnit 4 ha una disposizione per questo, chiamato Assume
:
@Test
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException {
//this line will cause the test to be branded as "ignored" when "isCircleCI"
//(the machine running ubuntu is running this test) is true.
Assume.assumeFalse(BootstrappingUtilities.isCircleCI());
//an ignored test will typically result in some qualifier being put on the results,
//but will also not typically prevent a green-ton most platforms.
//setup
URL url = DLLTestFixture.class.getResource("USERDLL.dll");
String path = url.toURI().getPath();
path = path.substring(0, path.lastIndexOf("/"));
//act
NativeLibrary.addSearchPath("USERDLL", path);
Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class);
//assert
assertThat(dll).isNotNull();
}
Basta usare l'istruzione return - nella maggior parte dei casi che passerà come pass(). – topchef
@topchef quel singolo commento colpisce il martello sulla testa, mentre tutti gli altri dibattono su quale sia accettabile e quale no. –
Alcuni sistemi di test (perl Test :: Simple) hanno superato e fallito asserzioni. Junit, tuttavia, conta il numero di _test methods_ che passano e falliscono. Quindi Junit non ha lo stesso uso per un metodo 'pass'. –