Mockito when (). ThenReturn () throws nullpointerExceptions

I am trying to use Mockito to create a Mock object that is returned from a Mock object. In particular, I am trying to make fun of the PlayerConnection object that my program can use to obtain an IP address.

Read more about this PlayerConnection object here . It returns an InetSocketAddress , which can then return an InetAddress , which can return a String with the IP address of the player. But I can't go that far, because my first when(class.function()).thenReturn(returnVariable) throws a NullPointerException . Here is my 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; } 

And here is the stack trace when(playerConnection.getAddress()).thenReturn(inetSocketAddress) place in 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:

I switched my stubs to doReturn().when().function() instead of when().thenReturn() to stop NullPointerExceptions , and this happened, but now I get a custom UnfinishedStubbingExceptions from Mockito.

A useful error code says that I have an incomplete stub somewhere, but I don’t see where it is. The error occurs in the second doReturn() method.

 /** * 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; } 
+5
source share
1 answer

Summary: InetSocketAddress.getAddress() is final, as documented . Due to its clever syntax, Mockito cannot easily drown or test final methods, and cannot even tell you when it tries and fails. In general, do not scoff at objects that you do not control, especially because of situations like this.

The useful error code for UnfinishedStubbingException identifies your problem (see option # 2, you naughty developer!):

 org.mockito.exceptions.misusing.UnfinishedStubbingException: Unfinished stubbing detected here: -> at Eg 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: Regular Mockito mocks work by taking an object and automatically and silently generating a subclass where all methods are overridden for delegation to Mockito. However, the Java compiler uses static dispatching for the final methods, so the calls to the final methods do not go directly to Mockito, instead they go on to implement the real method in InetSocketAddress. This instance of a subclass is never intended to interact with it and does not have any of its fields, so it is very easy to get a NullPointerException or other behavior - and all this happens before you interact with Mockito, t even benefit from the correct message about an error when using when(object.methodCall()).thenReturn() , because an unexpected NPE occurs when evaluating object.methodCall() before Mockito gets involved at all.

Performing other actions - doReturn(...).when(object).methodCall() - gives Mockito the ability to see doReturn and when , even if the methodCall call methodCall not pass Mockito. This gives Mockito the context to say that stubbing is not complete because Mockito cannot see the methodCall call.

For more information, see this SO ( Final Method, Mocking ) question and consider using the recent discard mockery of the final classes and methods that Mockito introduced in version 2.1.

+7
source

Source: https://habr.com/ru/post/1264909/


All Articles