tiebin-zhang / powermock

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

Random test fails for stubbing in @Before section #308

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1.I am stubbing static methods in @Before section (many times)
2.Then I call class's under test methods (that call mocked static methods)
3.I run this test
4.For one or more methods, an exception is thrown (I attach the exception just 
after the test class code - below)
Note: this test do not fail for every run!

test class code:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.mockito.Mockito.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassWithStatic.class})
public class PowerMockStressTest {

    UnderTest underTest = new UnderTest();
    @Before
    public void setUp(){
        PowerMockito.mockStatic(ClassWithStatic.class);
        for (int i = 0; i < 10; i++) { // 100*8executions
            createWhen();
        }
    }
    public void createWhen(){
        when(ClassWithStatic.a()).thenReturn("A");
        when(ClassWithStatic.b()).thenReturn("B");
        when(ClassWithStatic.c()).thenReturn("C");
        when(ClassWithStatic.d()).thenReturn("D");
        when(ClassWithStatic.e()).thenReturn("E");
        when(ClassWithStatic.f()).thenReturn("F");
        when(ClassWithStatic.g()).thenReturn("G");
        when(ClassWithStatic.h()).thenReturn("H");
    }

    @Test
    public void test1(){
        System.out.println(underTest.a1());
    }
    @Test
    public void test2(){
        System.out.println(underTest.b1());
    }
    @Test
    public void test3(){
        System.out.println(underTest.c1());
    }
    @Test
    public void test4(){
        System.out.println(underTest.d1());
    }
    @Test
    public void test5(){
        System.out.println(underTest.e1());
    }
    @Test
    public void test6(){
        System.out.println(underTest.f1());
    }
    @Test
    public void test7(){
        System.out.println(underTest.g1());
    }
    @Test
    public void test8(){
        System.out.println(underTest.h1());
    }

}

class ClassWithStatic {

    public static String a(){
        return "str";
    }
    public static String b(){
        return "str";
    }
    public static String c(){
        return "str";
    }
    public static String d(){
        return "str";
    }
    public static String e(){
        return "str";
    }
    public static String f(){
        return "str";
    }
    public static String g(){
        return "str";
    }
    public static String h(){
        return "str";
    }
}

class UnderTest {
    public String a1(){
        return ClassWithStatic.a();
    }
    public String b1(){
        return ClassWithStatic.b();
    }
    public String c1(){
        return ClassWithStatic.c();
    }
    public String d1(){
        return ClassWithStatic.d();
    }
    public String e1(){
        return ClassWithStatic.e();
    }
    public String f1(){
        return ClassWithStatic.f();
    }
    public String g1(){
        return ClassWithStatic.g();
    }
    public String h1(){
        return ClassWithStatic.h();
    }
}

EXCEPTION:

org.mockito.exceptions.base.MockitoException: 
'finalize' is a *void method* and it *cannot* be stubbed with a *return value*!
Voids are usually stubbed with Throwables:
    doThrow(exception).when(mock).someVoidMethod();
If the method you are trying to stub is *overloaded* then make sure you are 
calling the right overloaded version.
    at HardcoreStressTest.createWhen(HardcoreStressTest.java:30)
    at HardcoreStressTest.setUp(HardcoreStressTest.java:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:129)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:93)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:309)
    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:297)
    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:222)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:161)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:135)
    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:133)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:112)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
    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)

My environment (in from maven):
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.8.5</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>1.4.7</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito</artifactId>
            <version>1.4.7</version>
            <scope>test</scope>
        </dependency>

Original issue reported on code.google.com by michal.r...@gmail.com on 14 Jan 2011 at 3:52

GoogleCodeExporter commented 9 years ago
I downgrade Powermock from 1.4.7 to 1.4.6 and this error does NOT exist any 
more.
It looks like a bug exists in Powermock 1.4.7.

Original comment by michal.r...@gmail.com on 17 Jan 2011 at 9:56

GoogleCodeExporter commented 9 years ago
I'm seeing the exact same behavior.

I have 37 tests in my power-mock'ed test case, and some (usually 1 or 2, always 
different ones) fail randomly on the same stubbing code in @Before.

Thanks for the downgrade hint, will try that.

Original comment by matth...@qype.com on 24 Jan 2011 at 12:43

GoogleCodeExporter commented 9 years ago
Yep, I can confirm that everything checks out just fine with 1.4.6. Must be a 
regression in 1.4.7 then?

Original comment by matth...@qype.com on 24 Jan 2011 at 12:46

GoogleCodeExporter commented 9 years ago
Confirming this bug, tests are randomly failing. 

I think it is related to @PrepareForTest annotation, tests without this 
annotation look stable.

Original comment by crudolf....@googlemail.com on 8 Feb 2011 at 1:06

GoogleCodeExporter commented 9 years ago
This is something we need to look into. Seems like a race condition (finalize 
method should never be proxied) but I find it hard to see why it should work in 
1.4.6 and not 1.4.7.

Original comment by johan.ha...@gmail.com on 9 Feb 2011 at 10:22

GoogleCodeExporter commented 9 years ago
I have a similar issue with mocking a static with a side effect (shouldn't get 
called) using the special syntax:

doReturn(returnValue).when(MyStatic.class);
MyStatic.doSomething();

It also works intermittently (most of the times it works, but every few runs 
I'll get an error because it's calling the real static method which is not 
designed to be called in the test environment.

Could these issues be related? I will try downgrading to 1.4.6 and see if it 
also resolves it.

Original comment by dtabu...@gmail.com on 25 Feb 2011 at 2:35

GoogleCodeExporter commented 9 years ago
This has now been fixed in trunk (r1574). The reason why this happened was 
because the mock instance wasn't referenced long enough in some cases which 
caused it to be GC:ed znd thus the finalize method was called. We had a similar 
issue with EasyMock some years ago which was resolved but we obviously forgot 
about patching the Mockito extension as well.

The issue could occur in PowerMock 1.4.6 as well so it's not a 1.4.7 related 
issue.

Original comment by johan.ha...@gmail.com on 25 Feb 2011 at 9:45

GoogleCodeExporter commented 9 years ago
Thanks Johan, great work as always.

Original comment by matth...@qype.com on 25 Feb 2011 at 9:55

GoogleCodeExporter commented 9 years ago
maybe it's worth pushing out a release for this?

Original comment by davidkar...@gmail.com on 25 Feb 2011 at 9:58

GoogleCodeExporter commented 9 years ago
I agree it's fairly critical, should warrant a maintenance release

Original comment by matth...@qype.com on 25 Feb 2011 at 10:02

GoogleCodeExporter commented 9 years ago
Yeah maybe it's time to make a new release. I'll see if I can find some time 
for it during the weekend.

Original comment by johan.ha...@gmail.com on 25 Feb 2011 at 10:06

GoogleCodeExporter commented 9 years ago
And if someone would like to verify that it actually works that would be really 
nice.

Original comment by johan.ha...@gmail.com on 25 Feb 2011 at 10:07

GoogleCodeExporter commented 9 years ago
is there a workaround for this until a release becomes available?

Original comment by schauder...@gmail.com on 25 Feb 2011 at 12:05

GoogleCodeExporter commented 9 years ago
Not that I can think of :(

Original comment by johan.ha...@gmail.com on 25 Feb 2011 at 12:40

GoogleCodeExporter commented 9 years ago
I've released 1.4.8 now. Please tell me if it works for you or not.

Original comment by johan.ha...@gmail.com on 26 Feb 2011 at 9:46

GoogleCodeExporter commented 9 years ago
Seems to work fine so far

Original comment by davidkar...@gmail.com on 28 Feb 2011 at 1:28

GoogleCodeExporter commented 9 years ago
Great!

Original comment by johan.ha...@gmail.com on 28 Feb 2011 at 1:43

GoogleCodeExporter commented 9 years ago
Works fine for a class from my bug report. And also works fine for the project 
when I first found the bug.

Original comment by michal.r...@gmail.com on 28 Feb 2011 at 1:55