无法在 Spring Boot 项目中使用 SpringJUnit4ClassRunner 运行 powermockrule

Posted

技术标签:

【中文标题】无法在 Spring Boot 项目中使用 SpringJUnit4ClassRunner 运行 powermockrule【英文标题】:Cannot run powermockrule with SpringJUnit4ClassRunner in spring boot project 【发布时间】:2016-03-12 20:26:54 【问题描述】:

我有一个 spring boot 项目,需要使用 spring test runner 进行测试(这样我才能获得真正的应用程序上下文)并模拟静态方法。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes= MyApplication.class)
@PrepareForTest(StaticClass.class)
public class StaticClassTest 

    @Rule
    public PowerMockRule rule = new PowerMockRule();

    @Autowired
    HelloCmd hello;

    @Test
    public void testGetOne() 
        mockStatic(StaticClass.class);
        when(StaticClass.getNumber()).thenReturn(2);
        System.out.println(hello.getNumber());
    

我在运行测试时收到以下错误消息:

com.thoughtworks.xstream.converters.ConversionException: hello.hystrix.commands.HelloCmd$$EnhancerBySpringCGLIB$$a27be1be : hello.hystrix.commands.HelloCmd$$EnhancerBySpringCGLIB$$a27be1be
---- Debugging information ----
message             : hello.hystrix.commands.HelloCmd$$EnhancerBySpringCGLIB$$a27be1be
cause-exception     : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message       : hello.hystrix.commands.HelloCmd$$EnhancerBySpringCGLIB$$a27be1be
class               : hello.hystrix.commands.StaticClassTest
required-type       : hello.hystrix.commands.StaticClassTest
converter-type      : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
path                : /org.powermock.modules.junit4.rule.PowerMockStatement$1/outer-class/fNext/next/next/target/hello
line number         : 15
class[1]            : org.junit.internal.runners.statements.InvokeMethod
class[2]            : org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks
class[3]            : org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks
class[4]            : org.powermock.modules.junit4.rule.PowerMockStatement
class[5]            : org.powermock.modules.junit4.rule.PowerMockStatement$1
version             : null

如何解决这个问题?谢谢!

【问题讨论】:

【参考方案1】:

我从这里找到了修复 link 使用 PowerMockRunnerDelegate 而不是 PowerMockRule。

更新后的测试类将是:

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes= MyApplication.class)
@PrepareForTest(StaticClass.class)
public class StaticClassTest 

    @Autowired
    HelloCmd hello;

    @Test
    public void testGetOne() 
        mockStatic(StaticClass.class);
        when(StaticClass.getNumber()).thenReturn(2);
        System.out.println(hello.getNumber());
    

【讨论】:

【参考方案2】:

Spring、camel 和 powermock 单元测试:

PowerMockRule 也有同样的问题。我将其替换为以下注释

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)

.

同时从 Pom.xml 中删除依赖 powermock-module-junit4-rule 和 powermock-classloading-xstream 并且它可以工作。

 @RunWith(PowerMockRunner.class)
    @PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes =  StaticClassTest.ContextConfig.class )    
    @PrepareForTest( StaticClass.class )
    @PowerMockIgnore("javax.management.*")
    public class StaticClassTest extends DroolsHelper 

     @Before
    public void setup() 
        PowerMockito.mockStatic(StaticClass.class);

    

        @Produce(uri = "direct:start")
        private ProducerTemplate template;

        /**
         * 
         * ContextConfig.
         */
        @Configuration
        @Import(AppConfig.class)
        public static class ContextConfig extends SingleRouteCamelConfiguration 
         

            @Bean
            @Override
            public RouteBuilder route() 
                return new RouteBuilder() 
                    @Override
                    public void configure() 
                        from("direct:start").to("kie:kieSessionType?action=insertBody");
                    
                ;
            

        
 @Test
    public void test() 


        PowerMockito.when(StaticClass.anyMethod(Matchers.any(TestClass.class)).thenReturn(false);
        ......assert.........
    
    

【讨论】:

【参考方案3】:

建议在某种情况下使用 PowerMockRule,当

使用 Eclemma 和 PowerMockito API 导出代码覆盖率

由于字节码操作问题,“PowerMockito 与 Eclmemma 的使用提供 0% 覆盖率”是一个已知错误。

因此, 使用

@RunWith(PowerMockRunner.class) 和 @PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)

当代码覆盖率不是 JUnit 开发期间的主要关注点时。但事实并非如此。

我需要为定义的测试用例导出代码覆盖率信息

静态、私有、最终类型的方法 具有访问修饰符 static、private、final 的类 在@PrepareForTest 中声明测试类

因此我不得不使用 PowermockRule。

我不得不删除那些前面提到的注释。

但不知何故,PowerMockRule 的使用对我不起作用。

我添加了下面提到的工件

    <!-- powermock-module-junit4-rule -->
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4-rule</artifactId>
        <version>2.0.2</version>
        <scope>test</scope>
    </dependency>

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

    <!-- powermock-classloading-base -->
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-classloading-base</artifactId>
        <version>2.0.2</version>
        <scope>test</scope>
    </dependency>

在线建议还包括“使用 Java 代理进行引导”

建议。

【讨论】:

以上是关于无法在 Spring Boot 项目中使用 SpringJUnit4ClassRunner 运行 powermockrule的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot是什么

spring boot 实践总结(转)

Spring Boot使用Maven工具自动重启SpringBoot项目 | 热部署

Spring Boot:Spring Boot整合Logback和PageHelper

如何使用 Spring Boot 和嵌入式 Tomcat 配置此属性?

spring boot 项目设置默认访问路径方法