4

I have a spring boot project that needs to test with spring test runner(so that I can get the real application context) and mock the static method.

@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());
    }
}

And I got following error message when run the test:

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

How to fix this? Thanks!

snowery
  • 468
  • 1
  • 6
  • 18

3 Answers3

18

I found a fix from here link to use PowerMockRunnerDelegate instead of PowerMockRule.

The updated test class would be:

@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());
    }
}
snowery
  • 468
  • 1
  • 6
  • 18
3

Spring, camel & powermock unittest:

I had also same problem with PowerMockRule. I replaced it with following annotations

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

.

Also remove dependencies powermock-module-junit4-rule & powermock-classloading-xstream from Pom.xml and it works.

 @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.........
    }
    }
Narayan Yerrabachu
  • 1,714
  • 1
  • 19
  • 31
0

Use of PowerMockRule had been advised for a situation, when

  • To derive code coverage using Eclemma along with the use of PowerMockito API

It is a known bug that "Usage of PowerMockito along with Eclmemma gives 0% Coverage" because of ByteCode Manipulation Issues.

Thus, use

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

when Code Coverage is not the primary concern during JUnit Development. But that shouldn't be the case.

I needed to derive Code Coverage infromation for the Test cases defined for

  • Methods of type static, private, final
  • Classes with Access Modifier static, private, final
  • To declare Test Class inside @PrepareForTest

Hence I had to use PowermockRule.

I had to remove those previously mentioned annotations.

But somehow, usage of PowerMockRule is not working for me.

I added below mentioned artifacts

    <!-- 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>

Online advises also include "Bootstrapping using a Java agent"

Advise.

Philip Dilip
  • 181
  • 2
  • 4