Mockito NullPointerException在InvocationMatcher上调用equals

时间:2014-01-27 20:39:09

标签: java junit mockito

我是Mockito的新手,在尝试模拟第三方课时遇到错误。

堆栈追踪:

java.lang.NullPointerException
at MockitoTest.equals(MockitoTest.java:34)
at org.mockito.internal.invocation.InvocationMatcher.matches(InvocationMatcher.java:58)
at org.mockito.internal.stubbing.InvocationContainerImpl.findAnswerFor(InvocationContainerImpl.java:75)
at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:87)
at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:38)
at org.mockito.internal.creation.MethodInterceptorFilter.intercept(MethodInterceptorFilter.java:51)
at MockitoTest$$EnhancerByMockitoWithCGLIB$$cde393a2.getSomethingElse(<generated>)
at MockitoTestTest.test(MockitoTestTest.java:19)

Mockito正在调用此mock上的equals方法,该方法没有设置一些私有成员。代码:

public void test() {
    final String something = "something";
    final String somethingElse = "somethingElse";

    MockitoTest mt = Mockito.mock(MockitoTest.class);
    when(mt.getSomething()).thenReturn(something);
    when(mt.getSomethingElse()).thenReturn(somethingElse);

被模拟的类定义如下:

public class MockitoTest {

private final String something;
private volatile String somethingElse;

public MockitoTest(String theThing){
    something = theThing;
}

public String getSomething(){
    return something;
}

public String getSomethingElse(){
    return somethingElse;
}

@Override
public final int hashCode() {
    return something.hashCode();
}

@Override
public final boolean equals(Object o) {
    if(!(o instanceof MockitoTest))
        return false;
    return something.equals(((MockitoTest)o).something);
}

}

很明显,来自equals()的NPE正在发生,因为构造函数没有运行,并且没有设置'某事'。

我的问题:为什么会在第二次拨打电话时发生这种情况?有没有办法阻止调用equals方法?我做错了吗?

注意:上面的示例是为了显示发生的错误而设计的。我试图模拟的真正的类是在第三方库中,不容易改变。它不是简单的构造,它需要一种在第三方包之外不可见的类型。如果没有在我们的软件包中编写我的测试,那么我可以采取其他方法来模拟它,如上所述?

1 个答案:

答案 0 :(得分:2)

我很确定您的问题是{I} equalshashCode在您尝试模拟的类中final。 Mockito需要覆盖这些方法;所以这个课程可能是不可赎回的。

无论如何,嘲笑第三方课通常是件坏事。您是否有可能重构您的应用程序以便包装第三方类?您的包装器应该只公开您需要使用的方法。编写单元测试时,可以模拟包装器。