web-dev-qa-db-ja.com

SpringBootTestでPowerMockRunnerを使用できない

私のプロジェクトでは、SpringBootTestを使用して統合テストを記述しようとしています。サードパーティの静的な最終クラスがあります。パワーモックでモックしてみました。しかし、@ 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
{
11
Ramp

「@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 {

}
8
abaghel

これらのいずれかを機能させることができませんでした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 ....
}
4
Jordan Shaw

以下の構成セットは私のために働きました:

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({<YourClass.class>})を使用して、静的メソッドをモックするクラスをセットアップします
0
dev1188