繁体   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