2015-04-09 7 views
13

È possibile generare un'eccezione ogni volta che viene chiamata una simulazione con argomenti non predefiniti? C'è Answers.RETURNS_SMART_NULLS, ma non è proprio quello di cui ho bisogno, dal momento che non funziona se null è un valore di ritorno legittimo, che non porta a NullPointerException, ma piuttosto a errori successivi.Come si fa a Mockito lanciare un'eccezione quando viene chiamata una simulazione con parametri non definiti?

Modifica: alcuni sfondi. Così, in Mockito quando si definisce un modello, è necessario specificare i valori di ritorno per ogni chiamata in questo modo:

when(myMock.someMethod(arg1, arg2)).thenReturn(returnValue); 

Quando myMock.someMethod viene chiamato con argomenti, per cui non ho dato un valore di ritorno nel test, restituisce semplicemente null. Mi piacerebbe configurarlo per bloccarsi subito e dirmi che ho dimenticato di definire il valore di ritorno per alcune combinazioni di parametri.

Modifica 2: c'erano suggerimenti per fornire un numero personalizzato defaultAnswer che genera eccezioni quando viene chiamato. Sfortunatamente, questo non funziona. Il metodo di risposta predefinita 'answer() viene chiamato anche se è presente una simulazione. Ecco un esempio:

public class Test { 
    public static class Adder { 
    public int add(int a, int b) { 
     return a + b; 
    } 
    } 

    public static final Answer<Object> THROW_ON_UNDEFINED_ARGS = new Answer<Object>() { 
    @Override 
    public Object answer(InvocationOnMock invocation) throws Throwable { 
     throw new IllegalArgumentException(
      String.format("Calling a mock with undefined arguments: %s %s", 
       invocation.getMethod(), 
       Arrays.toString(invocation.getArguments()))); 
    } 
    }; 

    public static void main(String[] args) { 
    Adder adderMock = mock(Adder.class, THROW_ON_UNDEFINED_ARGS); 
    when(adderMock.add(2, 3)).thenReturn(5); 
    System.out.println(adderMock.add(2, 3)); 
    } 
} 

L'eccezione viene generata anche se adderMock.add(2, 3) è definito.

+1

"È possibile generare un'eccezione ogni volta che viene chiamata una simulazione con argomenti non predefiniti?" - Cosa significa esattamente? Vuoi simulare il lancio di un'eccezione se alcuni parametri vengono passati? Quali argomenti non prefediati significano? – M4ks

+0

Quindi, in Mockito si definiscono i valori di ritorno per mock come questo: 'when (myMock.someMethod (arg1, arg2)). ThenReturn (result)'. Se 'myMock.someMethod' viene chiamato con altri argomenti, restituisce null.Voglio che fallisca subito e dimmi, quel finto fu chiamato con argomenti, per i quali non definivo il valore di ritorno. –

risposta

8

È possibile fornire un valore predefinito Answer nella costruzione della propria simulazione che genera sempre un'eccezione. Quindi ogni chiamata che viene stoppata si comporterà come al solito. Ogni cosa al di fuori di questi percorsi genererà un'eccezione. Qualcosa del genere:

final String arg = "some arg"; 
Collection<Object> object = mock(Collection.class, new Answer<Object>() { 
    @Override 
    public Object answer(InvocationOnMock invocation) throws Throwable { 
     throw new IllegalArgumentException("You cannot invoke " + invocation.getMethod() + 
            " with " + Arrays.toString(invocation.getArguments())); 
    } 
}); 
doReturn(true).when(object).add(arg); 

object.add(arg); // Goes ok 
object.add("azertyuiop"); // Throws the exception 
+0

Grazie. Sembra che questo 'Answer' possa essere riutilizzato e specificato come' @Mock (answer = thisAnswer) '. Mi chiedo perché questa non sia una delle scelte dell'enum "mockito.Answers". –

+4

È possibile utilizzare la classe esistente 'org.mockito.internal.stubbing.answers.ThrowsException' – Robertiano

+0

Mi sono sbagliato su @Mock BTW. Accetta solo i valori dell'enum 'Risposte', non una' Risposta 'arbitraria. –

4

In primo luogo, un po 'di "buona ingegneria" mormora: perché ti piacerebbe farlo? Mockito cerca di "promuovere" lo stile BDD - tu configuri (simula) le tue chiamate, esegui il codice e verifica che le interazioni siano esattamente come ti aspettavi, piuttosto che "non ha chiamato nient'altro" - Cerchi di fare qualcosa descritto in Finding irrelevant invocation? Generalmente se voglio prendere in giro tutti i casi, ma uno - questo mi fa chiedere se i miei test sono davvero OK.

In ogni caso, l'argomento :)

In Mockito, è possibile definire più when s con valori diversi, come

class Foo { 
    public String bar(int a) { 
     return "bar = " + a; 
    } 
} 

Mockito.when(task.bar(Matchers.anyInt())).thenReturn("L") 
Mockito.when(task.bar(3)).thenThrow(new IllegalAccessError()) 

task.bar(4); // returns "L" 
task.bar(3); //throws IllegalAccessError 

Si noti che l'ordine delle when s non importa. Le regole vengono elaborate in ordine inverso (o piuttosto sostituiscono gli abbinamenti effettivi). Nel mio codice prendiamo in giro per anyInt, poi per 3 - che funziona. Se lo si inverte, entrambe le chiamate a bar() restituiranno 'L'.

+0

Non ho intenzione di verificare che il metodo testato non chiami qualcosa. Voglio solo trovare rapidamente le chiamate nel mock che non ho specificato. RETURNS_SMART_NULLS aiuta, ma non funziona per i metodi per i quali null è un valore di ritorno legale. In questo momento sto eseguendo il debug proprio di un problema del genere. Il test fallisce a causa di un risultato errato. Ho il sospetto che sia perché un metodo fittizio ha restituito null invece del valore corretto. –

+1

È possibile stampare tutte le interazioni usando 'mock (Foo.class, withSettings(). VerboseLogging());' - per motivi di debug. Inoltre, quando esegui 'verify' nel test, Mockito stamperà tutte le interazioni con l'oggetto dato se la verifica fallisce – M4ks

+0

Grazie, la registrazione potrebbe aiutare. –

2

Basta puntare un altro modo è possibile farlo, utilizzando thenAnswer:

when(myMock.someMethod(anyString(), anyString())). 
      thenAnswer(new Answer<String>() { 
       @Override 
       public String answer(InvocationOnMock invocation) throws Throwable { 
        Object[] args = invocation.getArguments(); 
        String arg1 = (String) args[0]; 
        String arg2 = (String) args[1]; 

        if ("arg1".equals(arg1) && "arg2".equals(arg2)) return "someValue"; 

        throw new Exception(); 
       } 
      }); 

     myMock.someMethod("arg1", "arg2"); // Returns "someValue" 
     myMock.someMethod("xxx", "yyy"); // Throws Exception 

Speranza che aiuta.

Problemi correlati