2017-08-04 79 views
0

此示例代碼:的Mockito產生的StackOverflowError當模擬的方法被調用的equals()/ hashCode()方法

public final class FooBarTest { 
    @Test 
    public void test() { 
     final Foo foo = mock(Foo.class); 
     when(foo.getBar()).thenReturn(1); 
     new HashSet().add(foo); 
    } 

    private class Foo { 
     @Override 
     public final boolean equals(final Object other) { 
      return getBar() == 0; 
     } 

     public int getBar() { 
      return 0; 
     } 

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

產生無限循環並拋出異常:

java.lang.StackOverflowError 
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:57) 
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:43) 
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptSuperCallable(MockMethodInterceptor.java:119) 
    at de.weltraumschaf.maconha.FooBarTest$Foo$MockitoMock$217383798.getBar(Unknown Source) 
    at de.weltraumschaf.maconha.FooBarTest$Foo.equals(FooBarTest.java:24) 
    at org.mockito.internal.invocation.InvocationMatcher.matches(InvocationMatcher.java:81) 
    at org.mockito.internal.stubbing.InvocationContainerImpl.findAnswerFor(InvocationContainerImpl.java:82) 
    at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:90) 
    at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:32) 
    at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:36) 
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:57) 
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:43) 
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptSuperCallable(MockMethodInterceptor.java:119) 
    at de.weltraumschaf.maconha.FooBarTest$Foo$MockitoMock$217383798.getBar(Unknown Source) 
    at de.weltraumschaf.maconha.FooBarTest$Foo.equals(FooBarTest.java:24) 
    at org.mockito.internal.invocation.InvocationMatcher.matches(InvocationMatcher.java:81) 
    at org.mockito.internal.stubbing.InvocationContainerImpl.findAnswerFor(InvocationContainerImpl.java:82) 
    at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:90) 
    at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:32) 
    at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:36) 
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:57) 
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:43) 
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptSuperCallable(MockMethodInterceptor.java:119) 
    at de.weltraumschaf.maconha.FooBarTest$Foo$MockitoMock$217383798.getBar(Unknown Source) 
    at de.weltraumschaf.maconha.FooBarTest$Foo.equals(FooBarTest.java:24) 
    ... 

我調試進代碼,並在Mockito的深度迷失。我能看到的唯一情況是equals方法被稱爲正確的。我知道Mockito不存根equals/hashCode/toString。我也很清楚,HashSet調用equals方法來查看它是否已經有相同的元素。但是我無法弄清楚:爲什麼這個循環是無止境的?

使用的Mockito版本是2.8.9和JUnit 4.12。

+0

可能是由於Mockito使用equals方法本身來驗證它是同一個對象。如果您爲了減少問題而不重寫hash和equals會發生什麼? Mockito可能不是這方面最好的用例。 –

回答

2

因爲在調用堆棧有org.mockito.internal.invocation.InvocationMatcher#matches這基本上是
invocation.getMock().equals(candidate.getMock())(與invocation.getMock()是你的嘲笑Foo實例),這導致getBar一個呼叫時,嘲笑這將導致調用equals - >getBar - >模擬 - >equals - >getBar - >等...

相關問題