2017-03-01 251 views
5

我试图用Mockito来创建一个Mock对象,该对象从Mock对象中返回。具体来说,我试图嘲笑我的程序可用于检索IP地址的PlayerConnection对象。Mockito when()。thenReturn()throws nullpointerExceptions

你可以找到更多关于这个PlayerConnection objecthere。它返回一个InetSocketAddress,然后可以返回一个InetAddress,它可以返回String与播放器的IP。但我不能得到那么多,因为我的第一个when(class.function()).thenReturn(returnVariable)抛出一个NullPointerException。这里是我的代码:

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

而这里的堆栈跟踪,存在的在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) 

编辑:

我转我的存根doReturn().when().function()而不是when().thenReturn()停止NullPointerExceptions,和它确实,但现在我从Mockito获得定制UnfinishedStubbingExceptions

有用的错误代码说我有一个未完成的存根,但我不知道它在哪里。该错误发生在第二个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

请参阅http:// stackoverflow。COM /问题/ 34308877 /如何对模拟的方法调用和返回值,而无需运行最方法。 – Tunaki

+0

我不明白。你有同样的错误,同样的答案是使用'doReturn(inetSocketAddress).when(playerConnection).getAddress()'就像上面提到的那样,而你没有这样做(所以你怎么能告诉它没有帮助? )。 – Tunaki

+0

对不起,我的意思是说它导致了另一个错误。编辑原始帖子。 –

回答

7

总结:InetSocketAddress.getAddress()是最终,as listed in the docs。由于其语法巧妙,Mockito不能轻易地存根或验证final方法,甚至无法告诉你它何时尝试和失败。一般来说,不要嘲笑你无法控制的物体,特别是因为这种情况。

为UnfinishedStubbingException乐于助人的错误代码标识您的问题(请参阅选项#2,你调皮的开发商!):

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 

详情:传统的Mockito被拍摄物体并自动嘲笑工作默默地生成一个子类,其中所有方法都被覆盖以委托给Mockito。但是,Java编译器利用静态分派来实现最终方法,因此对最终方法的调用不会直接进入Mockito,而是转而使用InetSocketAddress中的实际方法实现。这个子类实例并不打算与它交互,也没有设置任何字段,所以很容易得到NullPointerException或其他行为 - 并且在与Mockito进行交互之前发生的所有这些事情都是如此,当使用when(object.methodCall()).thenReturn()时,甚至可以获得理智的错误消息,因为在Mockito完全参与之前评估object.methodCall()时会发生意外的NPE。

做事情的另一way- doReturn(...).when(object).methodCall() -gives到的Mockito看到doReturnwhen即使调用methodCall不委托给了的Mockito机会。这给了Mockito上下文来说明存根未完成,因为Mockito无法看到methodCall呼叫。

有关更多信息,请参阅此SO问题(Final method mocking),并考虑使用Mockito在2.1版中引入的最近opt-in mocking of final classes and methods

+0

非常感谢。我没有意识到InetSocketAddress.getAddress()是最终的。 –

+0

不错的问题,很好的答案! – GhostCat

相关问题