编辑:这现在在此处作为 Powermock 的问题提交:http ://code.google.com/p/powermock/issues/detail?id=449&thanks=449&ts=1371519268
我正在使用 EasyMock 测试一些代码,该代码调用一个返回 ArrayListMultimap 的方法,我不想麻烦地构造一个充满模拟的集合对象,所以我决定简单地模拟 ArrayListMultimap 并让它返回我的任何模拟在标准模拟对象时尚中需要。ArrayListMultimap 原来是最终的,所以我在上面撒了一些 PowerMock 小精灵的灰尘。但是,当我运行测试时,我得到了:
java.lang.StackOverflowError
at java.lang.reflect.Method.copy(Method.java:143)
at java.lang.reflect.ReflectAccess.copyMethod(ReflectAccess.java:118)
at sun.reflect.ReflectionFactory.copyMethod(ReflectionFactory.java:282)
at java.lang.Class.copyMethods(Class.java:2757)
at java.lang.Class.getDeclaredMethods(Class.java:1793)
at org.easymock.internal.BridgeMethodResolver.getAllDeclaredMethods(BridgeMethodResolver.java:434)
at org.easymock.internal.BridgeMethodResolver.findBridgedMethod(BridgeMethodResolver.java:78)
at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:87)
at com.google.common.collect.ArrayListMultimap$$EnhancerByCGLIB$$2dd82dd1.equals(<generated>)
at org.easymock.internal.ExpectedInvocation.matches(ExpectedInvocation.java:85)
at org.easymock.internal.UnorderedBehavior.addActual(UnorderedBehavior.java:57)
at org.easymock.internal.MocksBehavior.addActual(MocksBehavior.java:87)
at org.easymock.internal.ReplayState.invokeInner(ReplayState.java:58)
at org.easymock.internal.ReplayState.invoke(ReplayState.java:46)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:40)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:85)
at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:94)
at com.google.common.collect.ArrayListMultimap$$EnhancerByCGLIB$$2dd82dd1.equals(<generated>)
at org.easymock.internal.ExpectedInvocation.matches(ExpectedInvocation.java:85)
at org.easymock.internal.UnorderedBehavior.addActual(UnorderedBehavior.java:57)
at org.easymock.internal.MocksBehavior.addActual(MocksBehavior.java:87)
at org.easymock.internal.ReplayState.invokeInner(ReplayState.java:58)
at org.easymock.internal.ReplayState.invoke(ReplayState.java:46)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:40)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:85)
at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:94)
at com.google.common.collect.ArrayListMultimap$$EnhancerByCGLIB$$2dd82dd1.equals(<generated>)
at org.easymock.internal.ExpectedInvocation.matches(ExpectedInvocation.java:85)
at org.easymock.internal.UnorderedBehavior.addActual(UnorderedBehavior.java:57)
at org.easymock.internal.MocksBehavior.addActual(MocksBehavior.java:87)
at org.easymock.internal.ReplayState.invokeInner(ReplayState.java:58)
at org.easymock.internal.ReplayState.invoke(ReplayState.java:46)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:40)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:85)
at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:94)
at com.google.common.collect.ArrayListMultimap$$EnhancerByCGLIB$$2dd82dd1.equals(<generated>)
at org.easymock.internal.ExpectedInvocation.matches(ExpectedInvocation.java:85)
at org.easymock.internal.UnorderedBehavior.addActual(UnorderedBehavior.java:57)
at org.easymock.internal.MocksBehavior.addActual(MocksBehavior.java:87)
at org.easymock.internal.ReplayState.invokeInner(ReplayState.java:58)
at org.easymock.internal.ReplayState.invoke(ReplayState.java:46)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:40)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:85)
at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:94)
at com.google.common.collect.ArrayListMultimap$$EnhancerByCGLIB$$2dd82dd1.equals(<generated>)
at org.easymock.internal.ExpectedInvocation.matches(ExpectedInvocation.java:85)
at org.easymock.internal.UnorderedBehavior.addActual(UnorderedBehavior.java:57)
最终我将问题提炼为这个例子:
import com.google.common.collect.ArrayListMultimap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.easymock.EasyMock.expect;
@RunWith(PowerMockRunner.class)
@PrepareForTest(ArrayListMultimap.class)
public class PurePowermockTest {
@Test
public void testPowerMockVsGuava() {
ArrayListMultimap map = PowerMock.createMock(ArrayListMultimap.class);
expect(map.put("foo", "bar")).andReturn(true);
PowerMock.replay(map);
map.put("foo", "bar"); // SOError!
}
}
上面的例子当然没有测试任何东西, map.put() 调用通常会在我正在测试的某个方法中。这段代码只是为了尽可能简洁地演示问题。我也知道我可以构建 ArrayListMultiMap 并返回它,但抛开这一点,模拟地图也应该起作用。我很确定这是powermock中的一个错误,但我的问题是:
我是否正确使用 PowerMock?这应该有效,还是我错过了关于 PowerMock 的功能或正确使用的一些东西?我正在使用 EasyMock.expect 方法,但我在 PowerMock 上没有看到等效方法,所以我认为这没问题...