【问题标题】:Getting javassist.NotFoundException with PowerMock and PowerRule in JUnit with Mockito使用 Mockito 在 JUnit 中使用 PowerMock 和 PowerRule 获取 javassist.NotFoundException
【发布时间】:2018-04-20 08:58:05
【问题描述】:

我已经在 J​​Unit 中用 Mockito 集成了 PowerMock 和 PowerRule。

这是我的依赖项:

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

我的测试课是:

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 正在调用我需要模拟的静态方法。 当我运行我的测试用例时,我得到javassist.NotFoundException: $Proxy88

完整的堆栈跟踪:

java.lang.RuntimeException: javassist.NotFoundException: $Proxy88 在 org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:187) 在 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(本机方法) 在 java.lang.Class.forName(Class.java:247) 在 org.powermock.api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:66) 在 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) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) 在 org.powermock.classloading.DeepCloner.cloneFields(DeepCloner.java:248) 在 org.powermock.classloading.DeepCloner.performClone(DeepCloner.java:128) 在 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) 在 org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49) 在 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) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 在 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 在 javassist.ClassPool.get(ClassPool.java:436) 在 org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:180) ... 46 更多

如果我将依赖项更改为

<dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-classloading-xstream</artifactId>
            <version>1.4.12</version>
            <scope>test</scope>
        </dependency>

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

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

【问题讨论】:

    标签: java maven junit4 mockito powermock


    【解决方案1】:

    自己找到了解决方案:

    仅使用以下依赖项(用于 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>
    

    现在我没有遇到上述任何一个异常

    【讨论】:

    • 我遇到了同样的问题,添加上述依赖项解决了这个问题。但我面临另一个问题,即代码没有达到调试断点。
    【解决方案2】:

    将 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>
    

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

    【讨论】:

    • 感谢@tak3shi 它对我有用!我还需要使用 -javaagent 标志。
    【解决方案3】:

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

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

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

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

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

    干杯,

    【讨论】:

      【解决方案4】:
      @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.}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-20
        • 1970-01-01
        • 2015-12-12
        • 2023-03-03
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 2021-12-12
        相关资源
        最近更新 更多