使用Mockito在JUnit中使用PowerMock和PowerRule获取javassist.NotFoundException

我已经将JUnit中的PowerMock和PowerRule与Mockito集成在一起。

这是我的依赖项:

 javassist javassist 3.12.0.GA   asm asm 3.3.1   cglib cglib 2.2.2   org.powermoc powermock-module-junit4 1.4.12 test   org.powermock powermock-api-mockito 1.4.12 test   org.powermock powermock-module-junit4-rule 1.4.12 test   org.powermock powermock-classloading-objenesis 1.4.12 test  

我的测试类是:

 public class TestClass extends AbstractShiroTest{ @Rule public PowerMockRule rule = new PowerMockRule(); @Autowired SomeService someService; @Before public void setUp(){ Map newMap = new HashMap(); newMap.put("userTimeZone", "Asia/Calcutta"); Subject subjectUnderTest = mock(Subject.class); when(subjectUnderTest.getPrincipal()).thenReturn(LMPTestConstants.USER_NAME); Session session = mock(Session.class); when(session.getAttribute(LMPCoreConstants.USER_DETAILS_MAP)).thenReturn(newMap); when(subjectUnderTest.getSession(false)).thenReturn(session); setSubject(subjectUnderTest); PowerMockito.mockStatic(CasSessionUtil.class); when(CasSessionUtil.getCarrierId()).thenReturn(1L); } @Test public void myTestMethod() { someService.doSomething(); } } 

doSomething正在调用我需要模拟的静态方法。 当我运行我的测试用例时,我得到javassist.NotFoundException: $Proxy88

完整堆栈跟踪:

java.lang.RuntimeException:javassist.NotFoundException:org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:187)中的$ Proxy88,位于org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:147)在java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)的java.lang.ClassLoader.loadClass(ClassLoader.java:252)的org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67)中位于org.powermock的org.powermock.api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:66)java.lang.Class.forName(Class.java:247)的java.lang.Class.forName0(Native Method)。位于org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:243)的ori.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128)上的api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:26) org.powermock.classloading.DeepCloner.perform中的.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 克隆(DeepCloner.java:128)org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248)org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128)atg.powermock.classloading.DeepCloner .cloneFields(DeepCloner.java:248)org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128)位于org.powermock.classloading的org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248)。位于org.powermock.classloading org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128)的org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248)中的DeepCloner.performClone(DeepCloner.java:128) .deepCloner.cloneFields(DeepCloner.java:248)位于org.powermock的org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128)org.powermock.classloading.DeepCloner.clone(DeepCloner.java:82)。 classload.DeepCloner.clone(DeepCloner.java:69)org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:89)at org。 powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78)位于org.springframework.test.context.junit4.statements.SpringRepeat的org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49)。评估(SpringRepeat.java:72)在Org.junit org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)的org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) .runners.ParentRunner $ 3.run(ParentRunner.java:193)org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:52)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)at at org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:42)位于org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks的org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:184)。在org.junit.internal.runners.statements.RunAfters.evaluate评估(RunBeforeTestClassCallbacks.java:61)(RunAfters.java:31 )org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)org.junit.runners.ParentRunner.run(ParentRunner.java:236)org.springframework.test.context。在org.eclipse.jdt.internal.junit.runner.TestExecution的org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)的junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)。运行(TestExecution.java:38)org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner。 java:683)org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)at or.e.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)引起:javassist.NotFoundException:$ proxy88 at javassist.ClassPool.get(ClassPool.java:436)at org.powermock.core.classloader.MockClassLoader.loadUnmockedClas s(MockClassLoader.java:180)……还有46个

如果我将依赖项更改为

  org.powermock powermock-classloading-xstream 1.4.12 test  

然后我得到一个不同的例外。 请参阅https://stackoverflow.com/questions/12176049/suggest-work-around-for-com-thoughtworks-xstream-converters-conversionexception (删除SO问题,需要10k)。

我甚至尝试过使用javassist 15版本,但这有同样的问题。

自己找到解决方案:

仅使用以下依赖项(适用于Power Mock和Power Rule)

    org.powermock powermock-api-mockito 1.4.12 test    org.powermock powermock-module-junit4-rule-agent 1.4.12 test  

现在我没有得到上述任何一个例外

将powermock-module-junit4-rule替换为powermock-module-junit4-rule-agent。

  org.powermock powermock-module-junit4-rule-agent test  

基于代理的引导程序和基于类加载的引导程序之间的主要区别在于您不会遇到类加载问题。

没有更多代码示例,我收集代码在测试中使用Spring。 所以我认为这个错误的原因是与Spring一起使用,它似乎生成了JDK代理( $Proxy88 )。

Powermock正在工作的方式是在新的类加载器中运行JUnit测试以修改这些类的字节码,不幸的是,它只能从真实文件中修改字节码,或者至少从可能的位置修改字节码。读取类二进制文件,因为java无法访问已经加载到JVM中的字节码。 (有可能以有限的方式与代理商合作)。

由于JDK代理在磁盘上不存在,因此无法读取或复制到特定的Powermock类加载器。

您正在编写的测试不是unit testing,因为它是使用Spring上下文运行的。 您可能想先写一个真正的unit testing 。 然后是一些集成测试你不需要模拟

你也应该避免使用静力学,因为它是一个可测试的噩梦。 您应该以不需要模拟静态调用的方式重写生产代码。

干杯,

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/test-servlet.xml") public class ControlCenterManagerImplTest { @Rule public PowerMockRule rule = new PowerMockRule(); //Powermock agent initialization not required and using maven dependency specified above by BHUVAN we can execute Power mock using spring.}