Mockito when()。thenReturn()抛出nullpointerExceptions

时间:2017-03-01 22:00:12

标签: java unit-testing mockito

我正在尝试使用Mockito创建一个从Mock对象返回的Mock对象。具体来说,我正在尝试模拟我的程序可以用来检索IP地址的PlayerConnection对象。

您可以找到有关此PlayerConnection object here的更多信息。它返回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以停止UnfinishedStubbingExceptions,但确实如此,但现在我从Mockito获得自定义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; } 方法发生错误。

{{1}}

1 个答案:

答案 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。

以另一种方式做事 - doReturn(...).when(object).methodCall() - 即使对doReturn的调用未委托给Mockito,Mockito也有机会看到whenmethodCall。这为Mockito提供了说明存根未完成的背景,因为Mockito无法看到methodCall电话。

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