使用Powermock测试Spring控制器

我有一个测试特定控制器的类,它工作正常

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:config/test-applicationContext-config.xml") @TestExecutionListeners({ WebContextTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) public class TestAdminController { //..... } 

我使用了mockito.org上的Google的Mockito库来模拟我的底层bean。

现在我的问题是:我有一些类需要被嘲笑,但他们有final方法,谷歌的mockito似乎没有解决这个问题。 我的一位同事建议使用powermock.org上的Powermock 。 但它需要使用@RunWith(PowerMockRunner.class)注释来注释测试器类。 如果我使用这个,我必须删除注释@RunWith(SpringJUnit4ClassRunner.class) ,这将给我带来问题,因为不会创建Spring测试上下文。 我怎么能避免这种情况?

建议我配置使用PowerMockRule而不是@RunWith注释

我的项目Maven依赖项如下

  org.powermock powermock-mockito-release-full 1.5 pom   org.powermock powermock-module-junit4-rule 1.5 test   org.powermock powermock-classloading-xstream 1.5 test  

现在我的class级看起来像这样(另一个控制器测试)

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:config/test-applicationContext-config.xml") @TestExecutionListeners({ WebContextTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) @PrepareForTest(ADSynchronizationImpl.class) public class ThirdPartyLoginControllerTest { @Rule public PowerMockRule rule = new PowerMockRule(); @Autowired private ThirdPartyLoginController thirtPartyLoginController; @Autowired private MockFactoryForControllers mockFactory; @Test public void testLoginActiveDirectory(){ } } 

但在运行我的测试后,我得到以下exception跟踪

com.thoughtworks.xstream.converters.ConversionException:javassist.NotFoundException:com.somecompany.analytics.manager.db.api.MlDao $$ EnhancerByMockitoWithCGLIB $$ b86d7415:javassist.NotFoundException:com.somecompany.analytics.manager.db.api。 MlDao $$ EnhancerByMockitoWithCGLIB $$ b86d7415 —-调试信息—-消息:javassist.NotFoundException:com.somecompany.analytics.manager.db.api.MlDao $$ EnhancerByMockitoWithCGLIB $$ b86d7415 cause-exception:java.lang。 RuntimeException cause-message:javassist.NotFoundException:com.somecompany.analytics.manager.db.api.MlDao $$ EnhancerByMockitoWithCGLIB $$ b86d7415 class:com.somecompany.ui.controllers.ThirdPartyLoginController required-type:com.somecompany.ui.controllers .ThirdPartyLoginController converter-type:com.thoughtworks.xstream.converters.reflection.ReflectionConverter path:/org.powermock.modules.junit4.rule.PowerMockStatement$1/outer-class/fNext/fTarget/thirtPartyLoginController/mlDao行号:14 class 1 :com.somecomp any.ui.controllers.ThirdPartyLoginControllerTest类2 :org.junit.internal.runners.statements.InvokeMethod类[3]
:org.powermock.modules.junit4.rule.PowerMockStatement类[4]
:org.powermock.modules.junit4.rule.PowerMockStatement $ 1版本
:null ——————————- at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java: 79)com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)at com.thoughtworks.xstream.converters.reflection .AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355)at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306)at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java) :234)com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72),位于com.thoughtworks.xstream.core的com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)。 TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)at co m.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355)位于com.thoughtworks.xstream.converters的com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306)。在com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)的com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)中的reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355)at com.thoughtworks.xstream.converters.reflection .AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306)at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConver ter.unmarshal(AbstractReflectionConverter.java:234)at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)at com .thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355)at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter .doUnmarshal(AbstractReflectionConverter.java:306)at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234)at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.j ava:66)at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)at com.thoughtworks.xstream.core .AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)在com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1052)的com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1036)com.thoughtworks。 xstream.XStream.fromXML(XStream.java:912)位于org.powermock的org.powermock.classloading.DeepCloner.clone(DeepCloner.java:54)的com.thoughtworks.xstream.XStream.fromXML(XStream.java:903) .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.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallback) s.java:74)atg.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java: 72)在org.jun.Unit4ClassRunner.runNild(BlockJUnit4ClassRunner.run:50)的org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)org.junit.runners.ParentRunner $ 3。运行(ParentRunner.java:238)org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:63)org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)org.junit.runners。在org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate的org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:229)中的ParentRunner.access $ 000(ParentRunner.java:53)(RunBeforeTestClassCallbacks.java: 61)at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClas sCallbacks.java:70)位于org.eclipse.jdt org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)的org.junit.runners.ParentRunner.run(ParentRunner.java:309) .internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)atg.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)org.eclipse.jdt.internal.junit .runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)atg.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)引起:java.lang.RuntimeException:javassist.NotFoundException:com.somecompany.idm .analytics.manager.db.api.MlDao $$ EnhancerByMockitoWithCGLIB $$ b86d7415 org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:199)at org.powermock.co re.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:149)位于com的java.lang.ClassLoader.loadClass(ClassLoader.java:356)的org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67) .thoughtworks.xstream.core.util.ClassLoaderReference.loadClass(ClassLoaderReference.java:31)at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:49)at com.thoughtworks.xstream.mapper.MapperWrapper.realClass (MapperWrapper.java:30)com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55)位于com.thoughtworks的com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)。 xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88)位于com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)的com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java: 79)在com.thoughtworks.xstream.mapper.MapperWrapper.r ealClass(MapperWrapper.java :)在com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)at com.thoughtworks位于com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)的.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)位于com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java) :30)com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74)位于com.thoughtworks.xstream.mapper的com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)。 MapperWrapper.realClass(MapperWrapper.java:30)位于com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)的com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)at com .thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapp er.java:30)com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:45)at com.thoughtworks.xstream com.thoughtworks.xstream.converters.ref上的com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:294)中的.converters.reflection.AbstractReflectionConverter.determineType(AbstractReflectionConverter.java:458).AbstractReflectionConverter.unmarshal (AbstractReflectionConverter.java:234)at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)… 57更多引起:javassist.NotFoundException:com.somecompany.analytics.manager.db.api。 MlDao $$ EnhancerByMockitoWithCGLIB $$ b86d7415 at javassist.ClassPool.get(ClassPool.java:450)at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:192)… 87更多

看看这篇文章 ,它解释了如何使用PowerMock和SpringJUnit4ClassRunner 。 基本上,您只需使用特殊的PowerMockRule规则 :

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:config/test-applicationContext-config.xml") @TestExecutionListeners({ WebContextTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) public class SpringExampleTest { @Rule public PowerMockRule rule = new PowerMockRule(); } 

编辑:似乎其他人遇到的问题与@PowerMockRule 相同 。 使用PowerMockAgent可以解决您的问题。 另见SO上的这个问题 。

您可以使用JMockit而不是Powermock。 它可以完成Powermock可以执行的所有操作,并且它不需要@RunWith子句,因此它不会干扰您的Spring测试运行器。 我发现PowerMockRule引入了比解决的问题更多的问题……

您也可以尝试使用注释来测试您的测试类

 @PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class) 

见这里的例子。