google-code-export / gwt-test-utils

Automatically exported from code.google.com/p/gwt-test-utils
1 stars 0 forks source link

Support for PowerMock #99

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Hello Gael,

this it clearly a wish for enhancement. 

Is is possible to support PowerMock. We are using sonar for code analysis and 
quality measurement. This leads to a lot of final methods (Design for 
extension) which can't be mocked with Mockito (my favorite) or EasyMock. 
PowerMock would solve the problem but needs it's own TestRunner.

Is there a way ?

Thx

Jürgen

Original issue reported on code.google.com by juergen....@gmail.com on 29 Nov 2011 at 2:44

GoogleCodeExporter commented 9 years ago
I've never used PowerMock I'll have a look at you to use it and how to override 
its custom classloader to be compatible with gwt-test-utils.

However, this will not be added in the coming 0.35 version.

Stay tuned ;-)

Original comment by gael.laz...@gmail.com on 29 Nov 2011 at 2:52

GoogleCodeExporter commented 9 years ago
Hello Gael,

as a Christmas wish of mine I would wish to push this issue a little bit.

In our Test we are running into several problems with static, final, etc 
classes and methods which hopefully would be solved by PowerMock 
(http://code.google.com/p/powermock/).

I really would like to help you, but I currently don't have the time to step 
into your integration of mocking frameworks. Probably if you put me 'on the 
rails' I could investigate whether there is a way to integrate PowerMock.

Happy Holiday

Jürgen 

Original comment by juergen....@gmail.com on 21 Dec 2011 at 10:57

GoogleCodeExporter commented 9 years ago
Hi Juergen,

I promise you to have a deep look at PowerMock this holiday to (at least) be 
able to state how to provide some support to it and how long it would take me 
to do it. But actually I hope to have something working before 2012 ;)

Stay tuned, and happy holiday to you :)

Original comment by gael.laz...@gmail.com on 22 Dec 2011 at 6:38

GoogleCodeExporter commented 9 years ago
Hi Juergen,

I  went deep into PowerMock's code to see how it would be possible to use the 
PowerMockRunner in gwt-test-utils and started to wrote a little POC. My 
conclusion are not so optimistic : gwt-test-utils classloading mechanism throws 
deep conflicts with PowerMock one.
Although both framework use javassist for bytecode manipulation, gwt-test-utils 
relies on the Classloader helper API provided by javassist (which is very 
flexible, easy to instrument) whereas PowerMock rewrites its own 
DeferredClassLoading with java.lang.ClassLoader. It is not design to be able to 
plug any other javassist standard class transformer...
I will contact PowerMock's owner to see if it would be possible to refactor 
their API so it could be pluggable with the standard javassist Classloader API.

But while reading the code, I saw PowerMock is able to modify classes to test 
through a javaagent instead of their custom classloading.
Their is the related documentation : 
http://code.google.com/p/powermock/wiki/PowerMockAgent
Maybe you could try to integrate gwt-test-utils and PowerMock this way, I think 
it should work :)

I'm waiting for your feedback

Cheers,

Gael

Original comment by gael.laz...@gmail.com on 17 Jan 2012 at 8:06

GoogleCodeExporter commented 9 years ago
Hello Gael,

My test ends early (see trace below). Probably  you could address this issue, 
if you contact the PowerMock developers.

Thx,

Jürgen

java.lang.ExceptionInInitializerError
    at contract.views.PMContractDetailControllerTest.<init>(PMContractDetailControllerTest.java:41)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:209)
    at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:258)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:255)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at com.octo.gwt.test.internal.runner.AbstractGwtRunner.run(AbstractGwtRunner.java:40)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    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.IllegalStateException: PowerMockRule can only be used with 
the system classloader but was loaded by 
com.octo.gwt.test.internal.GwtClassLoader@16d3536
    at org.powermock.modules.junit4.rule.PowerMockRule.<clinit>(PowerMockRule.java:28)
    ... 27 more

Original comment by juergen....@gmail.com on 19 Jan 2012 at 11:57

GoogleCodeExporter commented 9 years ago
Could you try to add this line in your META-INF/gwt-test-utils.properties file :

org.powermock. = delegate

This will tell GwtClassLoader to delegate the loading of all powermock classes 
to the system classloader.

Original comment by gael.laz...@gmail.com on 19 Jan 2012 at 12:24

GoogleCodeExporter commented 9 years ago
Hello Gael,

that worked around the previous problem. But then I get this.

java.lang.ClassCastException: 
de.heuboe.spingui.contract.client.views.ContractDetailView$$EnhancerByMockitoWit
hCGLIB$$6a6b36ab cannot be cast to org.mockito.cglib.proxy.Factory
    at org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:111)
    at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:51)
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:100)
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:58)
    at org.powermock.api.mockito.PowerMockito.mock(PowerMockito.java:138)
    at contract.views.PMContractDetailControllerTest.setup(PMContractDetailControllerTest.java:53)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at com.octo.gwt.test.internal.runner.AbstractGwtRunner.run(AbstractGwtRunner.java:40)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    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)

I've tried a non gwt-test-utils-example in the same project (same class path) 
which worked fine.

Any idea ?

Thx Jürgen

Original comment by juergen....@gmail.com on 19 Jan 2012 at 3:15

GoogleCodeExporter commented 9 years ago
That means that rg.mockito.cglib.proxy.Factory should be loaded by 
GwtClassLoader.

In the META-INF/gwt-test-utils.properties, maybe I could only tell the 
classloader to delegate the loading of the PowerMockRule, as it is expected to 
be loaded by the system classloader :

org.powermock.modules.junit4.rule.PowerMockRule = delegate

Or maybe : 

org.powermock.modules.junit4.rule.= delegate (if some other rule has to be 
loaded with the system classloader).

In general ClassCastException exceptions happen on two assignable class when 
they are loaded by two different classloaders 

Original comment by gael.laz...@gmail.com on 20 Jan 2012 at 7:48

GoogleCodeExporter commented 9 years ago
Hello Gael,

i'm still a little bit careful with my statement, but 

org.powermock.modules.junit4.rule. = delegate

seems to function !

Your my hero ;-)

Thx Jürgen

Original comment by juergen....@gmail.com on 20 Jan 2012 at 9:43

GoogleCodeExporter commented 9 years ago
Yeaaah :)

I'm not closing this issue right now. If you could confirm in a couple of week 
that there is no limitation in the integration of PowerMock/javaagent and 
gwt-test-utils, I will write a wiki page on it and close the issue ;)

Original comment by gael.laz...@gmail.com on 20 Jan 2012 at 10:15

GoogleCodeExporter commented 9 years ago
Hello Gael,

I fear we were to happy to soon.

Powermock does initialize without throwing any exeption, but unfortunately it 
also skips preparation of the classes. 
I digged in it a little deeper and found that it does not recognize it's own 
annotiation 'PrepareForTest'. I guessed that this problem again results from 
code loaded by different classloaders and added:

org.powermock.core.classloader.annotations. = delegate

to the META-INF/gwt-test-utils.properties file.

Now Powermock finds it's annotation but the gwt-test-utils are unhappy.

java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at org.powermock.modules.agent.PowerMockClassRedefiner.redefine(PowerMockClassRedefiner.java:55)
    at org.powermock.modules.agent.support.PowerMockAgentTestInitializer.redefine(PowerMockAgentTestInitializer.java:49)
    at org.powermock.modules.agent.support.PowerMockAgentTestInitializer.initialize(PowerMockAgentTestInitializer.java:41)
    at org.powermock.modules.junit4.rule.PowerMockRule.apply(PowerMockRule.java:34)
    at org.junit.runners.BlockJUnit4ClassRunner.withRules(BlockJUnit4ClassRunner.java:354)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:270)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at com.octo.gwt.test.internal.runner.AbstractGwtRunner.run(AbstractGwtRunner.java:40)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    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.UnsupportedOperationException: ERROR: GWT.create() is only 
usable in client code!  It cannot be called, for example, from server code.  If 
you are running a unit test, check that your test case extends GWTTestCase and 
that GWT.create() is not called from within an initializer or constructor.
    at com.google.gwt.core.client.GWT.create(GWT.java:91)
    at com.google.gwt.user.client.ui.UIObject.<clinit>(UIObject.java:187)
    ... 26 more

Any idea.

Thx Jürgen

Original comment by juergen....@gmail.com on 23 Jan 2012 at 8:18

GoogleCodeExporter commented 9 years ago
It seems that the gwt-test-utils classloading mechanism is totally bypassed now.

I think we will have to debug PowerMock's initialisation to see which class 
loading should be delegate to the system classloader and which can't.

Original comment by gael.laz...@gmail.com on 23 Jan 2012 at 9:55

GoogleCodeExporter commented 9 years ago

Original comment by gael.laz...@gmail.com on 7 Aug 2012 at 10:05