I am currently working on implementing a unit test for our Exit Code Manager that were implemented using static methods. The problem that I encounter is how can I mock the executeExit, which calls System.exit(), method so that it would not terminate all the test.
I tried spying on the SampleClass however it still continue on exiting the program whenever I run the test. Another solution that I try is to mock the whole class and use the doCallRealMethod for the method under test. However, this solution it faulty because (1) class under test are not undergoing code coverage, and (2) it is somehow testing the mocked class instead of the real class under test. I also tried mocking the System.class but it is also not working.
All kinds of help are pretty much appreciated. THANKS!
Below is a sample code similar to our method structure.
public class SampleClass{
public static void methodA(){
//do something here
executeExit();
public static void executeExit(){
//doing some stuff
System.exit(exitCode);
}
}
Below is a sample code of how I run my test:
@RunWith(PowerMockRunner.class)
@PrepareForTest(SampleClass)
public class SampleClassTest {
@Test
public void testMethodA(){
PowerMockito.spy(SampleClass.class);
PowerMockito.doNothing().when(SampleClass.class,"executeExit");
SampleClass.methodA();
}
}
I would test your code like this:
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
public class SampleClassTest {
@Rule
ExpectedSystemExit exit = ExpectedSystemExit.none();
@Test
public void testMethodA() {
exit.expectSystemExitWithStatus(-1);
SampleClass.methodA();
}
}
You need following dependency
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.16.1</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
</exclusion>
</exclusions>
</dependency>
Or if you do not want to import that dependency you can do it like:
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;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ SampleClass.class })
public class SampleClassTest {
@Test
public void testMethodA() {
PowerMockito.spy(SampleClass.class);
PowerMockito.doNothing().when(SampleClass.class);
SampleClass.executeExit();
SampleClass.methodA();
PowerMockito.verifyStatic();
SampleClass.executeExit();
}
}