2017-03-01 22 views
5

Próbuję użyć Mockito do stworzenia obiektu Mock, który zostanie zwrócony z obiektu Mock. W szczególności próbuję wykpić obiekt PlayerConnection, którego mój program może użyć do pobrania adresu IP.Mockito, gdy(). ThenReturn() wyrzuca nullpointerExceptions

Możesz znaleźć więcej informacji na temat tego PlayerConnection objecthere. Zwraca ona wartość InetSocketAddress, która może następnie zwrócić wartość InetAddress, która może zwrócić wartość String z adresem IP odtwarzacza. Ale nie mogę zajść tak daleko, ponieważ mój pierwszy when(class.function()).thenReturn(returnVariable) rzuca NullPointerException. Oto mój kod:

/** 
* 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; 
} 

A oto ślad stosu, występujących w when(playerConnection.getAddress()).thenReturn(inetSocketAddress):

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:

ja przestawił moje odcinki do doReturn().when().function() zamiast when().thenReturn() zatrzymać NullPointerExceptions i tak, ale teraz dostaję zwyczaj UnfinishedStubbingExceptions od Mockito.

Pomocny kod błędu mówi, że mam gdzieś niedokończony skrót, ale nie widzę, gdzie on jest. Błąd występuje w drugiej metodzie doReturn().

/** 
* 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

Zobacz http: // stackoverflow.com/questions/34308877/how-to-mock-method-call-and-return-value-without-running-the-method. – Tunaki

+0

Nie rozumiem. Masz ten sam błąd, a ta sama odpowiedź to użycie 'doReturn (inetSocketAddress) .when (playerConnection) .getAddress()' jak wspomniano, a ty tego nie robisz (więc jak możesz powiedzieć, że to nie pomogło?). – Tunaki

+0

Przepraszam; Chciałem powiedzieć, że spowodował kolejny błąd. Edycja oryginalnego wpisu. –

Odpowiedz

7

Podsumowanie:InetSocketAddress.getAddress() jest ostateczna as listed in the docs. Ze względu na jego sprytną składnię, Mockito nie może łatwo zatępić lub zweryfikować metod, i nie może nawet powiedzieć, kiedy próbuje i nie. Ogólnie rzecz biorąc, nie kpisz z obiektów, nad którymi nie masz kontroli, szczególnie z powodu takich sytuacji.

Pomocny kod błędu dla UnfinishedStubbingException identyfikuje problem (patrz opcja nr 2, ty niegrzeczny dewelopera!):

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 

szczegóły: konwencjonalne Mockito drwi pracy poprzez obiekt i automatycznie generowanie w cichy podklasy, w której wszystkie metody są nadpisywane w celu delegowania do Mockito. Jednak kompilator Java korzysta z wysyłania statycznego dla ostatecznych metod, więc wywołania do ostatecznych metod nie trafiają bezpośrednio do Mockito, zamiast tego przechodzą do rzeczywistej implementacji metody w InetSocketAddress. Ta instancja podklasy nigdy nie jest przeznaczona do interakcji i nie ma ustawionych żadnych jej pól, więc bardzo łatwo jest uzyskać NullPointerException lub inne zachowanie - i wszystko to dzieje się przed interakcją z Mockito, więc nie nawet przy korzystaniu z when(object.methodCall()).thenReturn() uzyskujesz korzyść ze zdrowego komunikatu o błędzie, ponieważ nieoczekiwany NPE ma miejsce podczas oceniania object.methodCall() zanim Mockito w ogóle się zaangażuje.

robienia rzeczy pozostałe drodze, doReturn(...).when(object).methodCall() -gives Mockito szansę zobaczyć doReturn i when nawet jeśli wezwanie do methodCall nie przekazywać Mockito. To daje Mockito kontekst do powiedzenia, że ​​stubbing jest niedokończony, ponieważ Mockito nie widzi połączenia methodCall.

Aby uzyskać więcej informacji, zobacz pytanie "Tak" (Final method mocking) i rozważ użycie najnowszego opt-in mocking of final classes and methods wprowadzonego przez Mockito w wersji 2.1.

+0

Dziękuję bardzo. Nie zdawałem sobie sprawy, że metoda InetSocketAddress.getAddress() była ostateczna. –

+0

Ładne pytanie, dobra odpowiedź! – GhostCat

Powiązane problemy