2017-03-01 2 views
5

Ich versuche, Mockito zu verwenden, um ein Mock-Objekt zu erstellen, das von einem Mock-Objekt zurückgegeben wird. Insbesondere versuche ich ein Objekt PlayerConnection zu verspotten, das mein Programm verwenden kann, um eine IP-Adresse abzurufen.Mockito when(). ThenReturn() löst nullpointerExceptions

Sie können mehr über diese here finden. Es gibt eine InetSocketAddress zurück, die dann eine InetAddress zurückgeben kann, die eine String mit der IP des Players zurückgeben kann. Aber ich kann nicht so weit kommen, weil mein erster when(class.function()).thenReturn(returnVariable) einen NullPointerException wirft. Hier ist mein Code:

/** 
* Creates a partial mock of a connection that can return an ip address. 
* 
* @param String 
*   The IP to return when the connection gets asked. 
* @return 
*/ 
private PlayerConnection newConnection(String ipString) 
{ 
    PlayerConnection playerConnection = mock(PlayerConnection.class); 
    InetSocketAddress inetSocketAddress = mock(InetSocketAddress.class); 
    InetAddress inetAddress = mock(InetAddress.class); 

    when(playerConnection.getAddress()).thenReturn(inetSocketAddress); 
    when(inetSocketAddress.getAddress()).thenReturn(inetAddress); 
    when(inetAddress.getHostAddress()).thenReturn(ipString); 

    return playerConnection; 
} 

Und hier ist der Stack-Trace, bei when(playerConnection.getAddress()).thenReturn(inetSocketAddress) auftreten:

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.001 sec <<< FAILURE! 
ruleResponseTest(com.github.heartsemma.communitywall.ConnectionChecks.RuleManagerTest) Time elapsed: 0.001 sec <<< ERROR! 
java.lang.NullPointerException 
     at java.net.InetSocketAddress$InetSocketAddressHolder.access$500(InetSocketAddress.java:56) 
     at java.net.InetSocketAddress.getAddress(InetSocketAddress.java:334) 
     at com.github.heartsemma.communitywall.ConnectionChecks.RuleManagerTest.newConnection(RuleManagerTest.java:99) 
     at com.github.heartsemma.communitywall.ConnectionChecks.RuleManagerTest.ruleResponseTest(RuleManagerTest.java:44) 

Edit:

Ich habe meinen Stubs doReturn().when().function() statt when().thenReturn() geschaltet, um die NullPointerExceptions zu stoppen, und es tat, aber jetzt bekomme ich benutzerdefinierte UnfinishedStubbingExceptions von Mockito.

Der hilfreiche Fehlercode sagt, dass ich irgendwo einen unvollendeten Stummel habe, aber ich sehe nicht, wo es ist. Der Fehler tritt bei der zweiten Methode doReturn() auf.

/** 
* Creates a partial mock of a connection that can return an ip address. 
* 
* @param ipString The IP to return. 
*    
* @return A PlayerConnection object that can return a Host Address of the ipString but nothing else. 
*/ 
private PlayerConnection newConnection(String ipString) 
{ 
    PlayerConnection playerConnection = mock(PlayerConnection.class); 
    InetSocketAddress inetSocketAddress = mock(InetSocketAddress.class); 
    InetAddress inetAddress = mock(InetAddress.class); 

    doReturn(inetSocketAddress).when(playerConnection).getAddress(); 
    doReturn(inetAddress).when(inetSocketAddress).getAddress(); 
    doReturn(ipString).when(inetAddress).getHostAddress(); 

    return playerConnection; 
} 
+0

Siehe http: // stackoverflow.com/questions/34308877/how-to-mock-Methode-Aufruf-und-Rückgabewert-ohne-run-the-Methode. – Tunaki

+0

Ich verstehe es nicht. Sie haben den gleichen Fehler und die gleiche Antwort ist 'doReturn (inetSocketAddress) .when (playerConnection) .getAddress()' wie erwähnt, und Sie tun das nicht (also wie können Sie sagen, dass es nicht geholfen hat?). – Tunaki

+0

Entschuldigung; Was ich sagen wollte, war, dass es einen weiteren Fehler verursachte. Originalpost bearbeiten –

Antwort

7

Zusammenfassung:InetSocketAddress.getAddress() ist endgültig, as listed in the docs. Aufgrund seiner cleveren Syntax kann Mockito nicht einfach final Methoden stub oder verifizieren, und kann Ihnen nicht einmal sagen, wenn es versucht und versagt. Im Allgemeinen, verspotten Sie keine Objekte, die Sie nicht kontrollieren, insbesondere aufgrund von Situationen wie dieser.

Der hilfreiche Fehlercode für UnfinishedStubbingException identifiziert Ihr Problem (Option # 2, du bösen Entwickler sehen!):

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at 

E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
    when(mock.isOk()).thenReturn(true); 
    when(mock.isOk()).thenThrow(exception); 
    doThrow(exception).when(mock).someVoidMethod(); 
Hints: 
1. missing thenReturn() 
2. you are trying to stub a final method, you naughty developer! 
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed 

Details: Herkömmliche Mockito spotten Arbeit durch ein Objekt zu nehmen und automatisch und Erzeugen einer Unterklasse, in der alle Methoden überschrieben werden, um sie an Mockito zu delegieren. Der Java-Compiler nutzt jedoch den statischen Versand für finale Methoden, sodass Aufrufe an finale Methoden nicht direkt an Mockito weitergeleitet werden, sondern stattdessen an die tatsächliche Methodenimplementierung in InetSocketAddress. Diese Unterklasseninstanz ist nicht dafür vorgesehen, mit Feldern interagiert zu werden, und hat auch keine ihrer Felder festgelegt. Daher ist es sehr einfach, NullPointerException oder ein anderes Verhalten zu erhalten - und all dies geschieht, bevor Sie mit Mockito interagieren. t sogar den Vorteil einer vernünftigen Fehlermeldung, wenn Sie when(object.methodCall()).thenReturn() verwenden, weil die unerwartete NPE während der Auswertung object.methodCall() passiert, bevor Mockito überhaupt beteiligt wird.

Dinge zu tun, die anderen Weg- doReturn(...).when(object).methodCall() -Gibt Mockito die Chance doReturn und when zu sehen, auch wenn der Anruf an methodCall nicht zu Mockito delegieren. Dies gibt Mockito den Kontext, um zu sagen, dass der Stubbing unvollendet ist, weil Mockito den methodCall Aufruf nicht sehen kann.

Weitere Informationen finden Sie in dieser SO-Frage (Final method mocking) und in Betracht ziehen, die neueste opt-in mocking of final classes and methods, die Mockito in Version 2.1 eingeführt.

+0

Vielen Dank. Ich wusste nicht, dass InetSocketAddress.getAddress() endgültig war. –

+0

Nette Frage, nette Antwort! – GhostCat

Verwandte Themen