簡體   English   中英

當在equals()/ hashCode()中調用模擬方法時,Mockito會產生StackOverflowError

[英]Mockito produces StackOverflowError when mocked method is called in 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方法被稱為right。 我知道Mockito不存根equals / hashCode / toString 我也很清楚,HashSet調用equals方法來查看其中是否已經有一個equal元素。 但是我不明白的是:為什么這個循環是無止境的?

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

因為在調用org.mockito.internal.invocation.InvocationMatcher#matchesorg.mockito.internal.invocation.InvocationMatcher#matches ,基本上是
invocation.getMock().equals(candidate.getMock())invocation.getMock()是您的getBar Foo實例),這會導致對getBar的調用, getBargetBar被嘲笑會導致對equals -> getBar >模擬-> equals -> getBar >等等...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM