【问题标题】:Cannot use PowerMockRunner with SpringBootTest无法将 PowerMockRunner 与 SpringBootTest 一起使用
【发布时间】:2017-01-09 15:54:51
【问题描述】:

对于我的项目,我正在尝试使用 SpringBootTest 编写集成测试。我有第 3 方静态最终课程。我尝试用 Power mock 模拟它。但是当尝试使用它@SpringBootTest 时,会抛出异常。

这是我的示例代码

@RunWith(PowerMockRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes =    SpringTestConfig.class
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest(IdGenerator.class)
public class RestTestIT
{
   @Before
   public void setUp() throws Exception
   {
       PowerMockito.mockStatic(IdGenerator.class);
   }
 ..
}

配置:

@Configuration
@EnableAutoConfiguration
@ComponentScan("com.xx.yy.zz")

public class SpringTestConfig
{
}

抛出异常:

2016-09-01 11:35:50.945 ERROR 18649 --- [           main] o.s.boot.SpringApplication               : Application startup failed

java.lang.IllegalArgumentException: Cannot find class [com.xx.yy.zz.SpringTestConfig$$EnhancerBySpringCGLIB$$414ee08e]
    at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:287) ~[na:4.3.2.RELEASE]
    at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.getConfigurationClasses(MockitoPostProcessor.java:147) ~[na:1.4.0.RELEASE]
    at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:132) ~[na:1.4.0.RELEASE]
    at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.postProcessBeanFactory(MockitoPostProcessor.java:126) ~[na:1.4.0.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:284) ~[na:4.3.2.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:174) ~[na:4.3.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:681) ~[na:4.3.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:523) ~[na:4.3.2.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[na:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[na:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369) ~[na:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:313) ~[na:1.4.0.RELEASE]
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:111) [na:1.4.0.RELEASE]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) [na:4.3.2.RELEASE]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) [na:4.3.2.RELEASE]
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) [na:4.3.2.RELEASE]
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) [na:4.3.2.RELEASE]
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) [na:4.3.2.RELEASE]
    at org.springframework.boot.test.autoconfigure.AutoConfigureReportTestExecutionListener.prepareTestInstance(AutoConfigureReportTestExecutionListener.java:46) [na:1.4.0.RELEASE]
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) [na:4.3.2.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) [na:4.3.2.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) [na:4.3.2.RELEASE]
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) [na:4.3.2.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) [na:4.3.2.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) [na:4.3.2.RELEASE]
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [na:4.3.2.RELEASE]
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [na:4.3.2.RELEASE]
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) [na:4.3.2.RELEASE]
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:143) [na:na]
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:136) [na:na]
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:127) [na:na]
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:136) [na:na]
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106) [powermock-module-junit4-common-1.6.1.jar:na]
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) [powermock-module-junit4-common-1.6.1.jar:na]
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59) [powermock-module-junit4-1.6.1.jar:na]
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264) [surefire-junit4-2.16.jar:2.16]
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153) [surefire-junit4-2.16.jar:2.16]
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124) [surefire-junit4-2.16.jar:2.16]
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200) [surefire-booter-2.16.jar:2.16]
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153) [surefire-booter-2.16.jar:2.16]
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103) [surefire-booter-2.16.jar:2.16]
Caused by: java.lang.ClassNotFoundException: com.xx.yy.zz.SpringTestConfig$$EnhancerBySpringCGLIB$$414ee08e
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_92]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_92]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_92]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_92]
    at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:178) ~[powermock-core-1.6.1.jar:na]
    at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:68) ~[powermock-core-1.6.1.jar:na]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_92]
    at org.springframework.util.ClassUtils.forName(ClassUtils.java:250) ~[na:4.3.2.RELEASE]
    at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:284) ~[na:4.3.2.RELEASE]
    ... 47 common frames omitted

Spring Boot 版本:1.4.0.RELEASE

         <dependency>
             <groupId>org.powermock</groupId>
             <artifactId>powermock-module-junit4</artifactId>
             <version>1.6.1</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.powermock</groupId>
             <artifactId>powermock-api-mockito</artifactId>
             <version>1.6.1</version>
             <scope>test</scope>
         </dependency>

我在这里缺少什么?是springBoot的错误吗?

解决方法: 我找到了一个解决方法来使用 SpringApplicationConfiguration,但是这个类在 SpringBootTest 中已被弃用。所以使用起来不太舒服。

@RunWith(PowerMockRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@SpringApplicationConfiguration(classes = SpringTestConfig.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest(IdGenerator.class)

public class RestTestIT
{

【问题讨论】:

    标签: spring spring-boot integration-testing powermockito


    【解决方案1】:

    以下配置对我有用:

    SpringBoot 版本:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.3.RELEASE</version>
        <relativePath/>
    </parent>
    
    <dependencies>    
        <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
           <groupId>org.powermock</groupId>
           <artifactId>powermock-module-junit4</artifactId>
           <version>2.0.4</version>
           <scope>test</scope>
        </dependency>
        <dependency>
           <groupId>org.powermock</groupId>
           <artifactId>powermock-api-mockito2</artifactId>
           <version>2.0.4</version>
           <scope>test</scope>
        </dependency>
     </dependencies>
    

    根据以下条件更改您的代码:

    • 如果您的 Spring 引导测试类已经在使用 @RunWith(SpringRunner.class),则将其替换为 @RunWith(PowerMockRunner.class)
    • 使用注解@PowerMockRunnerDelegate(SpringRunner.class) 让 Power 模拟委托给 SpringRunner.class
    • 正如上面 Jordan Shaw 所建议的,使用 @PowerMockIgnore 排除类
    • 使用@PrepareForTest({&lt;YourClass.class&gt;}) 设置您的类,该类具有要模拟的静态方法

    【讨论】:

      【解决方案2】:

      我无法让其中任何一个工作,我正在运行 Java 12、SpringBoot 2.1.7、PowerMock 2.0.0,但我确实得到了以下编译

      @SpringBootTest
      @RunWith(PowerMockRunner.class)
      @PowerMockRunnerDelegate(SpringRunner.class)
      @PrepareForTest(FileUtils.class)
      @PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "javax.xml.transform.*", "org.xml.*", "javax.management.*", "javax.net.ssl.*", "com.sun.org.apache.xalan.internal.xsltc.trax.*"})
      public class CallControllerTest { 
           .... tests here ....
      }
      

      【讨论】:

        【解决方案3】:

        我在使用“@SpringBootTest”和 Powermock 模拟最终课程时遇到了类似的问题。我使用以下方法解决了这个问题。您的 SpringTestConfig 类应如下所示。

        @ContextConfiguration
        public class SpringTestConfig
        {
        
        }
        

        您的 RestTestIT 类应该如下所示。

        @RunWith(PowerMockRunner.class)
        @SpringBootTest(webEnvironment = WebEnvironment.MOCK,classes = SpringTestConfig.class)
        @PowerMockRunnerDelegate(SpringRunner.class)
        @PrepareForTest(IdGenerator.class)
        public class RestTestIT {
        
        }
        

        【讨论】:

        • 谢谢!这解决了我的问题。万一其他人有同样的问题:我的 Config 类被注释为@Configuration,但它必须是@ContextConfiguration
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-12-27
        • 1970-01-01
        • 2019-10-20
        • 2014-11-29
        • 2017-03-07
        • 2013-07-30
        • 2014-11-23
        相关资源
        最近更新 更多