5

I have a class which tests specific controller and it works fine

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

I have used there Google's Mockito library from mockito.org to mock my underlying beans.

Now my question is the following: I have some classes which need to be mocked also, but they have final methods and Google's mockito seems not resolving this issue. One of my collegues suggested to use Powermock from powermock.org. But it requires to annotate the tester class with @RunWith(PowerMockRunner.class) annotation. If I use this I have to remove the annotation @RunWith(SpringJUnit4ClassRunner.class) and this will give me problems cause the Spring test context will not be created. How I can avoid this situation?

After suggestion I have configured to use PowerMockRule instead of @RunWith annotation

My project Maven dependencies are as follows

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

Now my class looks like this (another controller test)

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

    }
}

But after running my test I'm getting the following exception trace

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 ---- Debugging information ---- message : 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 line number : 14 class1 : com.somecompany.ui.controllers.ThirdPartyLoginControllerTest class2 : org.junit.internal.runners.statements.InvokeMethod class[3]
: org.powermock.modules.junit4.rule.PowerMockStatement class[4]
: org.powermock.modules.junit4.rule.PowerMockStatement$1 version
: null ------------------------------- at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:79) 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.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.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.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.java: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) at 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) at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78) at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at 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 org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: java.lang.RuntimeException: javassist.NotFoundException: com.somecompany.idm.analytics.manager.db.api.MlDao$$EnhancerByMockitoWithCGLIB$$b86d7415 at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:199) at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:149) at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:67) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) at com.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) at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79) at 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(MapperWrapper.java:30) at 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(MapperWrapper.java:30) at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74) at 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(MapperWrapper.java:30) at 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(MapperWrapper.java:30) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30) at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:45) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.determineType(AbstractReflectionConverter.java:458) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:294) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) ... 57 more Caused by: 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 more

Arsen Alexanyan
  • 3,061
  • 5
  • 25
  • 45

3 Answers3

6

Have a look at this article which explains how to use PowerMock and SpringJUnit4ClassRunner. Basically, you just have to use a 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();

}

Edit: it seems that other people had the same problem as you regarding @PowerMockRule. Using PowerMockAgent instead could solve your case. See also this anwer on SO.

Community
  • 1
  • 1
Bastien Jansen
  • 8,756
  • 2
  • 35
  • 53
  • I have tried it, but it seems X-Stream library under powermock is bug prone which is said also in your posted article – Arsen Alexanyan Mar 05 '13 at 14:30
  • Actually the article says XStream is more robust than Objenesis, the bugs they mention seem to appear with Objenesis. I've used XStream on other projects (not with PowerMock) and never had any problem. Did you encounter such bugs? – Bastien Jansen Mar 05 '13 at 14:41
  • Thanks for your suggestions, after using it with spring I have got error. I have edited the post to be more clear – Arsen Alexanyan Mar 06 '13 at 07:47
  • 1
    Could you look if you have multiple versions of Mockito in your classpath? Such errors often happen when two different classloaders load two different versions of a same dependency. `mvn dependency:tree` can help you figure this out. – Bastien Jansen Mar 06 '13 at 08:55
  • Yes it seems that I had multiple versions on classpath. But after fixing that I've got another error. I have changed exception trace – Arsen Alexanyan Mar 06 '13 at 10:11
  • I edited my answer, perhaps `PowerMockAgent` will solve your problem. Anyway, it seems to be tricky to use PowerMock in a Spring integration test :) – Bastien Jansen Mar 06 '13 at 13:00
  • Thanks your posted SO answer was helpful! – Arsen Alexanyan Mar 06 '13 at 14:22
6

You could also try to annotate your test class with

@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)

See example here.

gce
  • 1,563
  • 15
  • 17
  • Also, add the `@RunWith(PowerMockRunner.class)` before the delegate part – KumarAnkit Dec 28 '18 at 12:44
  • Link of exemple dead – jpmottin Oct 13 '20 at 08:21
  • @jpmottin try looking inside previous versions, I was able to [find](https://github.com/powermock/powermock/blob/powermock-1.6.0/examples/spring-mockito-delegate/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java) this file for 1.6.0 tag. – gce Oct 15 '20 at 08:12
  • 1
    Thanks @gce can you update the provided link in the original message ? – jpmottin Oct 15 '20 at 09:13
3

You could use JMockit instead of Powermock. It can do everything Powermock can do, and it doesn't need an @RunWith clause so it doesn't interfere with your Spring test runner. I found that the PowerMockRule introduced more problems than it solved...

Justin Rowe
  • 2,356
  • 1
  • 20
  • 15