gordonad / powermock

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

TestCase is prepared for test automatically if its fully qualified name starts with the same fully qualified name as a class that's prepared for test #140

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Using PowerMock 1.2.5, try running the following three classes in a
JUnit launch:

=== MockTest.java ===
package com.dummy;

import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Mock.class})

public class MockTest {

   @Test
   public void test() {
       PowerMock.suppressConstructor(Mock.class);
       Mock tested = new Mock();
       Integer o = (Integer)Whitebox.getInternalState(tested,
"member");
       assertTrue(o == 23);
   }
}

=== TestMock.java ===
package com.dummy;

import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Mock.class})

public class TestMock {

   @Test
   public void test() {
       PowerMock.suppressConstructor(Mock.class);
       Mock tested = new Mock();
       Integer o = (Integer)Whitebox.getInternalState(tested,
"member");
       assertTrue(o == 23);
   }
}

=== Mock.java ===
package com.dummy;

public class Mock {
   public int member = 23;
}

=== END ===

I find that TestMock passes, but MockTest fails. If I rename MockTest
into something NOT starting with the string "Mock", e.g. MTest, both
will pass. What is going on here?

Original issue reported on code.google.com by johan.ha...@gmail.com on 21 Aug 2009 at 6:31

GoogleCodeExporter commented 9 years ago
The thing is that suppressConstructor doesn't suppress the constructor in the 
class
that you specify as the argument (see the documentation) unless you prepare the 
class
that instantiates the actual class. It only suppress the constructor in the 
super
class of the class (if the super class is not java.lang.Object). So in your case
suppressConstructor shouldn't do anything at all normally, which is why it 
works when
you rename the test case. However if you where to to prepare the actual test 
case for
test (i.e. prepare MTest.class as well) the constructor of Mock would indeed be
suppressed because it's MTest that creates the instance of Mock. Do you see the
difference? So in your particular case the suppressConstructor shouldn't 
actually
acheive anything (unless you add MTest.class to the @PrepareForTest 
annotation). You
might as well remove it actually.

However in this case when the test is named MockTest it (MockTest.class) 
actually
gets prepared even though you haven't specified it. This is where the 
problem/bug is.
The reason for this is that MockTest is located in the same package and starts 
with
the same name as your class under test (Mock.class). PowerMock then prepares 
both
Mock.class and MockTest.class which now causes the constructor of Mock to be
suppressed and thus the field is never initialized. If you would have moved 
MockTest
to a different package or renamed it to something not starting with "Mock" it
wouldn't have prepared MockTest for and thus the constructor of Mock wouldn't 
have
been suppressed.

Original comment by johan.ha...@gmail.com on 21 Aug 2009 at 7:07

GoogleCodeExporter commented 9 years ago
Perhaps the test case should always be prepared for test automatically? This 
would
make it easier to under stand how to final system classes as well.

Original comment by johan.ha...@gmail.com on 21 Aug 2009 at 7:20

GoogleCodeExporter commented 9 years ago

Original comment by johan.ha...@gmail.com on 21 Aug 2009 at 7:21

GoogleCodeExporter commented 9 years ago

Original comment by johan.ha...@gmail.com on 21 Aug 2009 at 7:21

GoogleCodeExporter commented 9 years ago

Original comment by johan.ha...@gmail.com on 21 Aug 2009 at 7:22

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Perhaps we should make use of wildcards (at least *) if subpackages should also 
be
removed?

Original comment by johan.ha...@gmail.com on 8 Sep 2009 at 6:11

GoogleCodeExporter commented 9 years ago
Classes that were accidentally prepared for test automatically if the fully 
qualified
name of the class started with the same fully qualified name as a class that 
were
prepared for test. This has now been resolved. This may lead to backward
incompatibility issues in cases where tests didn't prepare all necessary 
artifacts
for test.

Original comment by johan.ha...@gmail.com on 19 Sep 2009 at 3:25