2011-09-26 1 views
8

c'è un modo più elegante per fare un'eccezione genera un'eccezione in Android allora?Come testare assert lancia un'eccezione in Android

public void testGetNonExistingKey() { 
     try { 
      alarm.getValue("NotExistingValue"); 
      fail(); 
     } catch (ElementNotFoundException e) { 

     } 
} 

Qualcosa di simile non funziona ?!

@Test(expected=ElementNotFoundException .class) 

Grazie, Mark

risposta

5

Si sta utilizzando un test runner Junit4? L'annotazione @Test non funzionerà se stai eseguendo un test runner junit3. Controlla la versione che stai utilizzando.

In secondo luogo, il metodo consigliato per verificare le eccezioni nel codice è utilizzare una regola (introdotta in junit 4.7).

@Rule 
public ExpectedException exception = ExpectedException.none(); 

@Test 
public void throwsIllegalArgumentExceptionIfIconIsNull() { 
    // do something 

    exception.expect(IllegalArgumentException.class); 
    exception.expectMessage("Icon is null, not a file, or doesn't exist."); 
    new DigitalAssetManager(null, null); 
} 

È possibile continuare a utilizzare il @Test (previsto = IOException.class), ma l'ha il vantaggio che, se viene generata un'eccezione prima che l'exception.expect è chiamato, allora il test fallirà sopra.

+1

Android utilizza una versione 3.x di junit quindi sembra che non ci sia altro modo - tranne per includere junit4 e passare a questo dalla junit Android. – Mark

+0

Ho appena eseguito questo con junit: 4.12 e ho calcolato che exception.expectMessage ("Icona è null, non è un file o non esiste."); non fallisce il test se il messaggio previsto non corrisponde. – takesavy

2

Ecco come lo faccio. Creo un metodo statico chiamato assertThrowsException che accetta come argomenti una classe di eccezione prevista e un Runnable che contiene il codice sotto test.

import junit.framework.Assert; 

public SpecialAsserts { 
    public void assertThrowsException(final Class<? extends Exception> expected, final Runnable codeUnderTest) { 
     try { 
      codeUnderTest.run(); 
      Assert.fail("Expecting exception but none was thrown."); 
     } catch(final Throwable result) { 
      if (!expected.isInstance(result)) { 
       Assert.fail("Exception was thrown was unexpected."); 
      } 
     } 
    } 
} 

Questo è il codice di esempio per utilizzare l'asserzione speciale nella vostra classe di test (che si estende AndroidTestCase o uno dei suoi derivati):

public void testShouldThrowInvalidParameterException() { 

    SpecialAsserts.assertThrowsException(InvalidParameterException.class, new Runnable() { 
     public void run() { 
      callFuncThatShouldThrow(); 
     } 
    }); 

} 

Sì, c'è un sacco di lavoro, ma è meglio di porting junit4 ad Android.

+0

Non sono sicuro che "assertThrowsException" abbia ragione. Il 'Throwable' dal primo' Assert.fail' sarà catturato e nel certo caso non si tratta di un'istanza della classe di eccezione prevista il prossimo 'Assert.fail' sparerà. – SK9

3

Ho fatto qualcosa di molto simile a hopia's answer con un paio di miglioramenti. Ho fatto in modo che restituisca l'oggetto eccezione in modo che tu possa controllare il suo messaggio o qualsiasi altra proprietà, e ho dichiarato un'interfaccia Testable per sostituire Runnable perché Runnable non consente al tuo codice in test di verificare le eccezioni.

public interface Testable { 
    public void run() throws Exception; 
} 

public <T extends Exception> T assertThrows(
     final Class<T> expected, 
     final Testable codeUnderTest) throws Exception { 
    T result = null; 
    try { 
     codeUnderTest.run(); 
     fail("Expecting exception but none was thrown."); 
    } catch(final Exception actual) { 
     if (expected.isInstance(actual)) { 
      result = expected.cast(actual); 
     } 
     else { 
      throw actual; 
     } 
    } 
    return result; 
} 

Ecco un esempio di chiamarlo.

InvalidWordException ex = assertThrows(
    InvalidWordException.class, 
    new Testable() { 
     @Override 
     public void run() throws Exception { 
      model.makeWord("FORG", player2); 
     } 
    }); 

assertEquals(
     "message", 
     "FORG is not in the dictionary.", 
     ex.getMessage()); 
0

Con junit3 il seguente potrebbe aiutare.

public static void assertThrows(Class<? extends Throwable> expected, 
     Runnable runnable) { 
    try { 
     runnable.run(); 
    } catch (Throwable t) { 
     if (!expected.isInstance(t)) { 
      Assert.fail("Unexpected Throwable thrown."); 
     } 
     return; 
    } 
    Assert.fail("Expecting thrown Throwable but none thrown."); 
} 

public static void assertNoThrow(Runnable runnable) { 
    try { 
     runnable.run(); 
    } catch (Throwable t) { 
     Assert.fail("Throwable was unexpectedly thrown."); 
    } 
}