Mockito when().thenReturn()抛出nullpointerExceptions

J. *_*Doe 5 java unit-testing mockito

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

你可以PlayerConnection object 在这里找到更多相关信息.它返回一个InetSocketAddress然后InetAddress可以返回一个可以返回String与播放器的IP的a .但我无法走得那么远,因为我的第一次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;
}
Run Code Online (Sandbox Code Playgroud)

这是堆栈跟踪,发生在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)
Run Code Online (Sandbox Code Playgroud)

编辑:

我已经将我的存根切换到了,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;
}
Run Code Online (Sandbox Code Playgroud)

Jef*_*ica 7

摘要: InetSocketAddress.getAddress()是最终的,如文档中所列.由于其巧妙的语法,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  
Run Code Online (Sandbox Code Playgroud)

细节:传统的Mockito模拟工作通过获取一个对象并自动生成一个子类,其中所有方法都被覆盖以委托给Mockito.但是,Java编译器利用最终方法的静态分派,因此对最终方法的调用不会直接转到Mockito,而是转到InetSocketAddress中的实际方法实现.这个子类实例并不打算与之交互,也没有设置任何字段,所以很容易得到NullPointerException或其他行为 - 所有这些都发生在你与Mockito交互之前,所以你不要甚至在使用时也能获得理智的错误信息when(object.methodCall()).thenReturn(),因为object.methodCall()在Mockito参与之前,在评估时会发生意外的NPE .

以另一种方式doReturn(...).when(object).methodCall()做事 - 让Mockito有机会看到doReturn,when即使电话methodCall没有委托给Mockito.这给Mockito提供了上下文来说明存根未完成,因为Mockito无法看到methodCall电话.

有关更多信息,请参阅此SO问题(最终方法模拟)并考虑使用最近的选择模拟 Mockito在2.1版中引入的最终类和方法.