chcchangchc / powermock

Automatically exported from code.google.com/p/powermock
Apache License 2.0
0 stars 0 forks source link

Can't get source code location when using PowerMock Classloader #351

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Failed to mock class with static initializer

What steps will reproduce the problem?

1. I have the following classes

public class Adder {
    public int Add(int a, int b){
        return a+b;
    }
}
--------------------
public abstract class AbstractController {
    public static String FOLDER=AbstractController.class.getProtectionDomain().getCodeSource().getLocation().getPath();
    public abstract int doWork();
    public void done(){
        System.out.println(FOLDER);
        System.out.println("Done");
    }
}
--------------------
public class Controller extends AbstractController {
    @Override
    public int doWork() {
        Adder adder=new Adder();
        int result=adder.Add(11,10);
        System.out.println(result);
        done();
        return result;
    }
}

2. Then I write a junit unit test class as below.

@RunWith(PowerMockRunner.class)
@PrepareForTest(Controller.class)
public class TestController {

    @Test
    public void testDoWork() throws Exception {
        Adder adder=mock(Adder.class);
        when(adder.Add(11, 10)).thenReturn(100);
        whenNew(Adder.class).withNoArguments().thenReturn(adder);
        Controller con=new Controller();
        assertEquals(100, con.doWork());
    }

    @Test
    public void testDone(){
        Controller con=new Controller();
        con.doWork();
    }

}

3. Both unit tests fail.
java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at javassist.runtime.Desc.getClassObject(Desc.java:44)
    at javassist.runtime.Desc.getClassType(Desc.java:153)
    at javassist.runtime.Desc.getType(Desc.java:123)
    at javassist.runtime.Desc.getType(Desc.java:79)
    at org.markey.learnjava.TestController.testDone(TestController.java:26)
    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.internal.runners.TestMethod.invoke(TestMethod.java:66)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:307)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:112)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    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.NullPointerException
    at org.markey.learnjava.AbstractController.<clinit>(AbstractController.java:4)
    ... 35 more

What is the expected output? What do you see instead?

It looks like the problem is caused by the following statement. 
public static String 
FOLDER=AbstractController.class.getProtectionDomain().getCodeSource().getLocatio
n().getPath();

I know I perhaps can suppress static initilizer. But the problem is if I do 
need FOLDER to be initialized? 

What version of the product are you using? On what operating system?

I am using Powermock 1.4.10 with Mockito and junit on Windows.

Please provide any additional information below.

The classes and unit test I supplied are just examples. They don't make much 
sense. Please don't take them serious.

Original issue reported on code.google.com by smartmar...@gmail.com on 14 Oct 2011 at 1:17

GoogleCodeExporter commented 9 years ago
You can suppress the static initializer by using the 
@SuppressStaticInitializerFor annotation. This is clearly mentioned in the 
documentation 
(http://code.google.com/p/powermock/wiki/SuppressUnwantedBehavior#Suppress_stati
c_initializer).

Original comment by johan.ha...@gmail.com on 21 Oct 2011 at 6:20

GoogleCodeExporter commented 9 years ago
Hi,

As I stated in this issue,I know I perhaps can suppress static initilizer. But 
the problem is if I do need FOLDER to be initialized,not simply supressed? How 
to do?

Original comment by smartmar...@gmail.com on 21 Oct 2011 at 7:44

GoogleCodeExporter commented 9 years ago
Ah sorry I read the issue too fast. What is causing the NPE? Is it e.g. the 
call to getProtectionDomain() or getCodeSource()?

I assume you don't get the NPE when you're testing the class without PowerMock?!

Original comment by johan.ha...@gmail.com on 24 Oct 2011 at 2:55

GoogleCodeExporter commented 9 years ago
The real NPE occurs when calling getLocation().

FYI. The following is the output(toString()) for each call.

1. getProtectionDomain()
ProtectionDomain  (null <no signer certificates>)
 org.powermock.core.classloader.MockClassLoader@84abc9
 <no principals>
 null

2.getCodeSource()
(null <no signer certificates>)

Original comment by smartmar...@gmail.com on 25 Oct 2011 at 12:30

GoogleCodeExporter commented 9 years ago
Sorry. Forgot to say. Your assumption is correct. I don't get the NPE when 
testing the class without PowerMock

Original comment by smartmar...@gmail.com on 25 Oct 2011 at 12:31

GoogleCodeExporter commented 9 years ago
Alright. This probably has to do with some bug or missing functionality in 
PowerMock's classloader. I'll accept it as an issue. Please give us a hand and 
try to investigate how it could be solved if you like. Issues like these are 
usually quite hard to track down and fix and I'm not sure I'll find the time to 
do so any time soon :(

Original comment by johan.ha...@gmail.com on 25 Oct 2011 at 8:11

GoogleCodeExporter commented 9 years ago
I'd love to help, but frankly speaking, I know little about Java class loader. 
Do you have any suggestions I can follow?

Original comment by smartmar...@gmail.com on 1 Nov 2011 at 1:14