Mock Static causing some side effects in other tests while in Eclipse

2,480 views
Skip to first unread message

Aaron

unread,
May 18, 2011, 1:25:25 PM5/18/11
to PowerMock
Hello happy Mockers,

I have an issue I believe is an issue with the way eclipse runs the
tests as I don't see this running while using my ant script. Let me
try to explain the problem I have, suppose the following scenario
(this is a legacy code with little opportunities to radically refactor
the code):

StaticJavaClass
ClassUnderTestDirectDependencyOnStatic <--- the class testing this
will mock static StaticJavaClass
ClassUnderTestIndirectDependencyOnStatic <--- the class testing this
will NOT care about mocking StaticJavaClass however it depends on it.

Using ant test: no issues everything runs fine.

Using eclipse: If I test independently they both pass all of their
tests if I test the entire suite I get all kinds of errors and
failures.

Has anyone faced this same problem?
Is there a way to "Undo" the mock static that I can run on the
@AfterClass thus not affecting the other class?

Thanks for the help,
--Aaron.

Johan Haleby

unread,
May 19, 2011, 2:17:20 AM5/19/11
to powe...@googlegroups.com
Hi,

I'm not really sure if I understand you completely but it sounds pretty strange. Are you sure that there are no side-effects in your test? Is it a standard junit test or a PDE test? Which version of PowerMock are you using?

Regards,
/Johan



--
You received this message because you are subscribed to the Google Groups "PowerMock" group.
To post to this group, send email to powe...@googlegroups.com.
To unsubscribe from this group, send email to powermock+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/powermock?hl=en.


Aaron

unread,
Jun 9, 2011, 12:28:49 PM6/9/11
to PowerMock
Hi Johan,

Thanks for the reply let me try to set an example:

Versions:
mockito-all-1.8.5
powermock-mockito-1.4-full

Suppose you have the following classes:

public class SampleWithStaticMethods {
private static int number=2;

public static int getTwo(){
return number;
}

public static int getFour(){
return 2 * number;
}
}

public class FirstTierSample {
public int getFour (){
return 2 * SampleWithStaticMethods.getTwo();
}
}

public class SecondTierSample {
public int getEight (){
FirstTierSample ftSample = new FirstTierSample();
return 2 * ftSample.getFour();
}
}

And you have the following test cases:

@RunWith(PowerMockRunner.class)
@SuppressStaticInitializationFor("sample.SampleWithStaticMethods")
@PrepareForTest(SampleWithStaticMethods.class)
public class FirstTierSampleTest {
@Test
public void testGetFourMockedToGetSix() {
PowerMockito.mockStatic(SampleWithStaticMethods.class);
Mockito.when(SampleWithStaticMethods.getTwo()).thenReturn(3);
FirstTierSample testObject = new FirstTierSample();
assertEquals(6, testObject.getFour());
}
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(SampleWithStaticMethods.class)
public class ZecondTierSampleTest {
@Test
public void testGetEight() {
SecondTierSample testObject = new SecondTierSample();
assertEquals(8, testObject.getEight());
}

@Test
public void testGetEightMockedToGetTwelve() {
PowerMockito.mockStatic(SampleWithStaticMethods.class);
Mockito.when(SampleWithStaticMethods.getTwo()).thenReturn(3);
SecondTierSample testObject = new SecondTierSample();
assertEquals(12, testObject.getEight());
}

@Test
public void testGetFour(){
assertEquals(4, SampleWithStaticMethods.getFour());
}
}

Using eclipse if I run each test class individually they both run
perfectly if I run the package sample I fail two test cases form the
second test class, now if I run this from within ant (as a junit
batchtest task) all test cases will run correctly.

It looks like on ant the @SuppressStaticInitializationFor was being
reverted every time it runs a test class but not on eclipse.

I hope this clears out the questions.

Regards,
--Aaron

Johan Haleby

unread,
Jun 9, 2011, 1:01:22 PM6/9/11
to powe...@googlegroups.com
I think it works in ant because it's forking the JVM for each test class whereas Eclipse don't. The problem could be that FirstTierSampleTest tells PowerMock (PM) to suppress the static init and thus it'll be suppressed for the entire suite because you cannot reload classes with Java classloaders. What you could try to do is to move the SuppressStaticInitializerFor annotation to the method level:

@RunWith(PowerMockRunner.class)
@PrepareForTest(SampleWithStaticMethods.class)
public class FirstTierSampleTest {

       @Test
       @SuppressStaticInitializationFor("sample.SampleWithStaticMethods")
       public void testGetFourMockedToGetSix() {
               PowerMockito.mockStatic(SampleWithStaticMethods.class);
               Mockito.when(SampleWithStaticMethods.getTwo()).thenReturn(3);
               FirstTierSample testObject = new FirstTierSample();
               assertEquals(6, testObject.getFour());
       }
}

Run the suite in Eclipse and see if that'll work. 

Regards,
/Johan

Aaron

unread,
Jun 9, 2011, 1:16:02 PM6/9/11
to PowerMock
Hi Johan,

Thanks again for the prompt response. I tried your suggestion however
this does not work. Any suggestions on where to find additional
information for how to modify how eclipse handles this, or if it is
possible to undo/revert the effects of the
@SuppressStaticInitializationFor annotation?

Regards,
--Aaron.

Johan Haleby

unread,
Jun 9, 2011, 1:38:20 PM6/9/11
to powe...@googlegroups.com
Try modifiing your second test like this:

@RunWith(PowerMockRunner.class)
public class ZecondTierSampleTest {
       @Test
       @PrepareForTest(SampleWithStaticMethods.class)
       public void testGetEight() {
               SecondTierSample testObject = new SecondTierSample();
               assertEquals(8, testObject.getEight());
       }

       @Test
       @PrepareForTest(SampleWithStaticMethods.class)
       public void testGetEightMockedToGetTwelve() {
               PowerMockito.mockStatic(SampleWithStaticMethods.class);
               Mockito.when(SampleWithStaticMethods.getTwo()).thenReturn(3);
               SecondTierSample testObject = new SecondTierSample();
               assertEquals(12, testObject.getEight());
       }

       @Test 
       @PrepareForTest(SampleWithStaticMethods.class)
       public void testGetFour(){
               assertEquals(4, SampleWithStaticMethods.getFour());
       }
}

Does that make any difference?

/Johan

Aaron

unread,
Jun 9, 2011, 1:43:23 PM6/9/11
to PowerMock
I tried this suggestion as well but it doesn't work either.

--Aaron.

Johan Haleby

unread,
Jun 9, 2011, 1:55:07 PM6/9/11
to powe...@googlegroups.com
Alright, I find it quite strange that one of them didn't work :/ Then I'm not really sure how to go about. I'm not an Eclipse user myself so I don't know how to configure junit fork mode in Eclipse. But do you really need to suppress the static initializer?

/Johan

Aaron

unread,
Jun 9, 2011, 2:06:26 PM6/9/11
to PowerMock
I'm not sure myself either, as far as how to fork in eclipse I'm also
researching this in other groups I'll try to post my findings.
As far as the use case the provided code is just a simple example to
depict the a current scenario, however in the legacy code we are
testing the answer is "yes" since this will inject so many
dependencies as it reads information from files and initializes some
other objects that will try to connect to the database and so on.

Thanks again for the help!

--Aaron.

On Jun 9, 11:55 am, Johan Haleby <johan.hal...@gmail.com> wrote:
> Alright, I find it quite strange that one of them didn't work :/ Then I'm
> not really sure how to go about. I'm not an Eclipse user myself so I don't
> know how to configure junit fork mode in Eclipse. But do you *really* need

Johan Haleby

unread,
Jun 9, 2011, 2:12:54 PM6/9/11
to powe...@googlegroups.com
I see. What I was trying to suggest is to use something we call "test chunking" which means that some tests are loaded with a new classloader. This is normally not recommended but in your situation where you need to suppress a static initializer in one test but leave it intact in another you'll need to use that approach. You can see an example of it here.

/Johan
Reply all
Reply to author
Forward
0 new messages