2015-04-09 9 views
13

Kann eine Ausnahme ausgelöst werden, wenn ein Schein mit nicht vordefinierten Argumenten aufgerufen wird? Es gibt Answers.RETURNS_SMART_NULLS, aber es ist nicht wirklich was ich brauche, da es nicht funktioniert, wenn null legitimer Rückgabewert ist, der nicht zu NullPointerException führt, sondern eher zu Fehlern später.Wie kann Mockito eine Ausnahme auslösen, wenn ein Mock mit nicht definierten Parametern aufgerufen wird?

Bearbeiten: etwas Hintergrund. Also, in Mockito, wenn Sie ein Modell zu definieren, geben Sie die Rückgabewerte für jeden Aufruf wie folgt aus:

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

Wenn myMock.someMethod mit Argumenten aufgerufen wird, für die ich keinen Rückgabewert im Test gegeben hat, es gibt einfach null zurück. Ich möchte es so konfigurieren, dass es sofort abstürzt und mir sagt, dass ich vergessen habe, den Rückgabewert für eine bestimmte Kombination von Parametern zu definieren.

Edit 2: Es gab Vorschläge, um eine benutzerdefinierte defaultAnswer, die Ausnahmen beim Aufruf ausgelöst würde. Leider funktioniert das nicht. Die Standardantworten 'answer() Methode wird aufgerufen, auch wenn ein Schein vorhanden ist. Hier ist ein Beispiel:

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)); 
    } 
} 

Die Ausnahme wird ausgelöst, obwohl adderMock.add(2, 3) definiert ist.

+1

"Ist es möglich, eine Ausnahme auszulösen, wenn ein Schein mit nicht vordefinierten Argumenten aufgerufen wird?" - Was bedeutet das genau? Sie möchten das Auslösen einer Ausnahme simulieren, wenn einige Parameter übergeben werden? Was nicht vorgefertigte Argumente bedeutet? – M4ks

+0

Also definieren Sie in Mockito die Rückgabewerte für Mocks wie folgt: 'when (myMock.someMethod (arg1, arg2)). ThenReturn (result)'. Wenn 'myMock.someMethod' mit einigen anderen Argumenten aufgerufen wird, wird null zurückgegeben.Ich möchte, dass es sofort scheitert und mir sagt, dass das Pseudo mit Argumenten aufgerufen wurde, für die ich keinen Rückgabewert definiert habe. –

Antwort

8

Sie könnten einen Standard Answer in der Konstruktion Ihres Mocks angeben, der immer eine Ausnahme auslöst. Dann wird jeder gestartete Anruf wie üblich funktionieren. Alles außerhalb dieser Pfade wird eine Ausnahme auslösen. So etwas wie das:

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

Danke. Es sieht so aus, als könnte 'Antwort' wiederverwendet und als '@Mock (answer = thisAnswer)' angegeben werden. Ich frage mich, warum dies nicht eine der Möglichkeiten in "mockito.Answers" enum ist. –

+4

Sie können die vorhandene Klasse 'org.mockito.internal.stubbing.answers.ThrowsException' verwenden. – Robertiano

+0

Ich habe mich bei @Mock BTW geirrt. Es akzeptiert nur Werte der Ansage "Answers", keine willkürliche "Answer". –

4

Zuerst ein bisschen "gute Technik" murmeln - warum möchten Sie das tun? Mockito versucht, den BDD-Stil zu "promoten" - Sie richten Ihre Aufrufe ein, Sie führen den Code aus und verifizieren, dass die Interaktionen genau so waren, wie Sie es erwartet haben, anstatt "es hat nichts anderes aufgerufen" Finding irrelevant invocation? Generell wenn ich alle Fälle verspotten will, aber einen - das lässt mich fragen, ob meine Tests wirklich OK sind.

Wie auch immer, zum Thema :)

In Mockito können Sie mehr when s mit verschiedenen Werten, wie

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 

Beachten Sie, dass die Reihenfolge der when s ist von Bedeutung definieren. Die Regeln werden in umgekehrter Reihenfolge verarbeitet (oder überschreiben die tatsächlichen Matching-Regeln). In meinem Code wir zuerst für AnyInt, dann für 3 - was funktioniert. Wenn Sie es umkehren - beide Aufrufe an bar() werden "L" zurückgeben.

+0

Ich habe nicht die Absicht zu überprüfen, dass die getestete Methode nicht etwas aufruft. Ich möchte nur die Anrufe in dem Mock, den ich nicht angegeben habe, schnell finden. RETURNS_SMART_NULLS hilft, aber es funktioniert nicht für Methoden, für die null ein zulässiger Rückgabewert ist. Im Moment debugge ich gerade solch ein Problem. Der Test schlägt aufgrund eines falschen Ergebnisses fehl. Ich vermute, dass dies darauf zurückzuführen ist, dass eine falsche Methode null anstelle des korrekten Werts zurückgegeben hat. –

+1

Sie können alle Interaktionen nur mit 'mock (Foo.class, withSettings(). VerboseLogging());' - zum Debuggen drucken. Darüber hinaus, wenn Sie im Test "verifizieren", Mockito wird alle Interaktionen mit dem gegebenen Objekt drucken, wenn die Überprüfung fehlschlägt – M4ks

+0

Danke, Protokollierung könnte helfen. –

2

Zeigen Sie einfach eine andere Art und Weise Sie das tun können, mit 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 

Hoffe, es hilft.

Verwandte Themen