java 使用 Mockito 在 JUnit 中使用 PowerMock 和 PowerRule 获取 javassist.NotFoundException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12190377/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting javassist.NotFoundException with PowerMock and PowerRule in JUnit with Mockito
提问by Bhuvan
I have integrated PowerMock and PowerRule in JUnit with Mockito.
我已经将 JUnit 中的 PowerMock 和 PowerRule 与 Mockito 集成在一起。
Here are my dependencies:
这是我的依赖项:
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.0.GA</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.powermoc</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-rule</artifactId>
<version>1.4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-classloading-objenesis</artifactId>
<version>1.4.12</version>
<scope>test</scope>
</dependency>
My test class is:
我的测试课是:
public class TestClass extends AbstractShiroTest{
@Rule
public PowerMockRule rule = new PowerMockRule();
@Autowired
SomeService someService;
@Before
public void setUp(){
Map<String, Object> newMap = new HashMap<String, Object>();
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
is calling a static method that I need to mock.
When I run my test case, I get javassist.NotFoundException: $Proxy88
.
doSomething
正在调用我需要模拟的静态方法。当我运行我的测试用例时,我得到javassist.NotFoundException: $Proxy88
.
Full stack trace:
完整的堆栈跟踪:
java.lang.RuntimeException: javassist.NotFoundException: $Proxy88 at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:187) at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:147) at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at org.powermock.api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:66) at org.powermock.api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:26) at org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:243) at org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) at org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) at org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) at org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) at org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) at org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) at org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) at org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) at org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) at org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) at org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) at org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) at org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) at org.powermock.classloading.DeepCloner.clone(DeepCloner.java:82) at org.powermock.classloading.DeepCloner.clone(DeepCloner.java:69) at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:89) at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78) at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: javassist.NotFoundException: $Proxy88 at javassist.ClassPool.get(ClassPool.java:436) at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:180) ... 46 more
java.lang.RuntimeException: javassist.NotFoundException: $Proxy88 at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:187) at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:147)在 org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:252) 在 java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) 在java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at org.powermock.api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:66) at org.powermock。 api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:26) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:243) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) :128) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.CloneFields(DeepCloner.CloneFields) java:248) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.performClone(DeepCloner.performClone) .java:128) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 在 org.powermock.classloading.DeepCloner。performClone(DeepCloner.java:128) at org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) at org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) at org.powermock.classloading.DeepCloner .clone(DeepCloner.java:82) 在 org.powermock.classloading.DeepCloner.clone(DeepCloner.java:69) 在 org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:89) 在 org.powermock.classloading。 ClassloaderExecutor.execute(ClassloaderExecutor.java:78) at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat. java:72) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 在 org.junit。runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org .junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) ) 在 org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 在 org.junit.internal.runners.statements.RunAfters.evaluate(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.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 在 org.eclipse .jdt.internal.junit.runner.TestExecution.run(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) 在 org.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。loadUnmockedClass(MockClassLoader.java:180) ... 46 更多
If I change the dependency to
如果我将依赖项更改为
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-classloading-xstream</artifactId>
<version>1.4.12</version>
<scope>test</scope>
</dependency>
then I get a different exception. Please see https://stackoverflow.com/questions/12176049/suggest-work-around-for-com-thoughtworks-xstream-converters-conversionexception(deleted SO question, requires 10k).
然后我得到一个不同的例外。请参阅https://stackoverflow.com/questions/12176049/suggest-work-around-for-com-thoughtworks-xstream-converters-conversionexception(已删除 SO 问题,需要 10k)。
I have even tried with javassist version 15, but that has the same problem.
我什至尝试过 javassist 版本 15,但也有同样的问题。
回答by Bhuvan
Found out the solution myself:
自己找到了解决办法:
Use the below dependencies (for Power Mock and Power Rule) only
仅使用以下依赖项(用于 Power Mock 和 Power Rule)
<!-- Required for PowerMock -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.4.12</version>
<scope>test</scope>
</dependency>
<!-- Required for PowerMockRule -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-rule-agent</artifactId>
<version>1.4.12</version>
<scope>test</scope>
</dependency>
Now I am not getting either of the above exceptions
现在我没有得到上述任何一个例外
回答by tak3shi
Replace powermock-module-junit4-rule with powermock-module-junit4-rule-agent.
将 powermock-module-junit4-rule 替换为 powermock-module-junit4-rule-agent。
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-rule-agent</artifactId>
<scope>test</scope>
</dependency>
The main difference between the agent based bootstrapper and the classloading based bootstrapper is that you don't run into classloading issues.
基于代理的引导程序和基于类加载的引导程序之间的主要区别在于您不会遇到类加载问题。
回答by Brice
Without more code samples I gather that the code is using Spring in the test. So I believe the reason for this error is that related to Spring use, which do seem to have generated JDK proxies (the $Proxy88
).
在没有更多代码示例的情况下,我认为代码在测试中使用了 Spring。所以我相信这个错误的原因是与 Spring 的使用有关,它似乎确实生成了 JDK 代理($Proxy88
)。
And the way Powermock is working is by running the JUnit test in a new classloader in order to modify the bytecode of these classes, unfortunately it is only possible to modify the bytecode from a the real file, or at least from a location where it's possible to read the class binary, as java cannot access bytecode already loaded in the JVM. (It may be possible with an agent in a limited way).
Powermock 的工作方式是在新的类加载器中运行 JUnit 测试以修改这些类的字节码,不幸的是,只能从真实文件或至少从可能的位置修改字节码读取类二进制文件,因为 java 无法访问已加载到 JVM 中的字节码。(代理可能以有限的方式实现)。
As JDK proxies do not exists on disk, they cannot be read, or copied to the specific Powermock classloader.
由于磁盘上不存在 JDK 代理,因此它们无法读取或复制到特定的 Powermock 类加载器。
The test you are writing is not a unit test as it is run with a Spring context. You might want to write a real Unit Testfirst. Then some Integration Test, in which you won't need mocks.
您正在编写的测试不是单元测试,因为它是在 Spring 上下文中运行的。您可能想先编写一个真正的单元测试。然后是一些集成测试,在其中您不需要 mocks。
Also you should avoid the use of statics, as it is a testability nightmare. You should rewrite your production code in a way where static calls don't need to be mocked.
此外,您应该避免使用静态,因为它是可测试性的噩梦。您应该以不需要模拟静态调用的方式重写生产代码。
Cheers,
干杯,
回答by gjosh
@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.}