使用Powermock测试Spring控制器

时间:2013-03-05 12:38:09

标签: java spring-mvc mockito powermock spring-test-mvc

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

@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个方法,Google的mockito似乎无法解决这个问题。我的一位同事建议使用powermock.org中的Powermock。但它需要使用@RunWith(PowerMockRunner.class)注释来注释测试器类。如果我使用它,我必须删除注释@RunWith(SpringJUnit4ClassRunner.class),这将给我带来问题,因为不会创建Spring测试上下文。我怎么能避免这种情况?

建议后,我已将其配置为使用PowerMockRule代替@RunWith注释

我的项目Maven依赖项如下

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-mockito-release-full</artifactId>
    <version>1.5</version>
    <type>pom</type>
</dependency> 
<dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4-rule</artifactId>
        <version>1.5</version>
        <scope>test</scope>
</dependency>
<dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-classloading-xstream</artifactId>
        <version>1.5</version>
        <scope>test</scope>
</dependency>

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

@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(){

    }
}

但是在运行我的测试后,我得到了以下异常跟踪

  

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   课程:   com.somecompany.ui.controllers.ThirdPartyLoginController required-type   :com.somecompany.ui.controllers.ThirdPartyLoginController   转换器类型:   com.thoughtworks.xstream.converters.reflection.ReflectionConverter   路径:   /org.powermock.modules.junit4.rule.PowerMockStatement$1/outer-class/fNext/fTarget/thirtPartyLoginController/mlDao   行号:14班1:   com.somecompany.ui.controllers.ThirdPartyLoginControllerTest类2   :org.junit.internal.runners.statements.InvokeMethod class [3]
  :org.powermock.modules.junit4.rule.PowerMockStatement类[4]
  :org.powermock.modules.junit4.rule.PowerMockStatement $ 1版本
  : 空值   ------------------------------- at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:79)     在   com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)     在   com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)     在   com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)     在   com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)     在   com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)     在   com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)     在com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1052)at   com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1036)at   com.thoughtworks.xstream.XStream.fromXML(XStream.java:912)at   com.thoughtworks.xstream.XStream.fromXML(XStream.java:903)at   org.powermock.classloading.DeepCloner.clone(DeepCloner.java:54)at   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.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)     在   org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)     在   org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)     在   org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)     在   org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)     在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:238)at   org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:63)at   org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)at at   org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:53)at at   org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:229)at at   org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)     在   org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)     在org.junit.runners.ParentRunner.run(ParentRunner.java:309)at   org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)     在   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)   引起:java.lang.RuntimeException:javassist.NotFoundException:   com.somecompany.idm.analytics.manager.db.api.MlDao $$ EnhancerByMockitoWithCGLIB $$ b86d7415     在   org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:199)     在   org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:149)     在   org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67)     在java.lang.ClassLoader.loadClass(ClassLoader.java:356)at   com.thoughtworks.xstream.core.util.ClassLoaderReference.loadClass(ClassLoaderReference.java:31)     在   com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:49)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.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.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.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.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)     在   com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:45)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.determineType(AbstractReflectionConverter.java:458)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:294)     在   com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234)     在   com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)     ... 57更多引起:javassist.NotFoundException:   com.somecompany.analytics.manager.db.api.MlDao $$ EnhancerByMockitoWithCGLIB $$ b86d7415     在javassist.ClassPool.get(ClassPool.java:450)at   org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:192)     ......还有87个

3 个答案:

答案 0 :(得分:6)

查看this article,了解如何使用PowerMock和SpringJUnit4ClassRunner。基本上,您只需使用special PowerMockRule rule

@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关于other people had the same problem似乎是PowerMockAgent。使用this anwer可以解决您的问题。另请参阅SO上的{{3}}。

答案 1 :(得分:6)

您还可以尝试使用

注释您的测试类
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)

参见示例here

答案 2 :(得分:3)

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