Reputation: 315
I have a class to which I must pass 2 arguments through its main method, if passed less than 2 args, it displays a system error message. I wrote a unit test for the main method here, when I run the test, it stops at "running" (shows neither pass nor fail). Please suggest.
Example.java
public class Example
{
private static String str1 = null;
private static String str2 = null;
public static void main(String[] args)
{
if( args.length != 2 )
{
call();
}
Example ex = new Example(args[0], args[1]);
ex.getData();
}
public Example(String str1, String str2)
{
Example.str1 = str1;
Example.str2 = str2;
}
public void getData(){
System.out.println("Name is: "+str1);
System.out.println("City is: "+str2);
}
private static void call()
{
System.err.println("Usage: String1 String2");
System.err.println("Where: ");
System.err.println(" String1 - Name");
System.err.println(" String1 - City");
System.exit(1);
}
}
ExampleTest.java
public class ExampleTest {
@Test
public void testPassingWrongNumberOfInputs() {
StringBuffer sb = new StringBuffer();
sb.append("Usage: String1 String2")
.append("Where: ")
.append(" String1 - Name")
.append(" String1 - City");
String expectedErrorMessage = sb.toString();
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
System.setErr(new PrintStream(outContent));
String[] args = {"one"};
Example.main(args);
assertEquals(expectedErrorMessage, outContent.toString());
}
}
Upvotes: 5
Views: 25496
Reputation: 1099
Rename the main method, and add a return value, so you can test it. Call this new method from main.
Upvotes: 0
Reputation: 315
I finally was able to write the unit test as shown in the following. I only tested if the method is hitting System.exit(1) code or not.
public class ExampleTest {
private SecurityManager m;
private TestSecurityManager sm;
@Before
public void setUp()
{
m = System.getSecurityManager();
sm = new TestSecurityManager ();
System.setSecurityManager(sm);
}
@After
public void tearDown()
{
System.setSecurityManager(m);
}
@Test
public void testPassingWrongNumberOfInputs() {
try {
Example.main(new String[] {"one"});
} catch (SecurityException se) {
assertEquals("1", se.getMessage());
}
}
}
class TestSecurityManager extends SecurityManager {
@Override
public void checkPermission(Permission permission) {
if ("exitVM".equals(permission.getName()))
{
throw new SecurityException("System.exit attempted and blocked.");
}
}
@Override
public void checkExit(int status) {
throw new SecurityException(Integer.toString(status));
}
}
Upvotes: 2
Reputation: 11992
How about the following:
class TestingSecurityManager extends SecurityManager {
@Override public void checkExit(int status) {
throw new SecurityException();
}
}
Then in your test...
public class ExampleTest {
@Test
public void testPassingWrongNumberOfInputs() {
StringBuffer sb = new StringBuffer();
sb.append("Usage: String1 String2")
.append("Where: ")
.append(" String1 - Name")
.append(" String1 - City");
String expectedErrorMessage = sb.toString();
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
System.setErr(new PrintStream(outContent));
String[] args = {"one"};
TestSecurityManager sm = new TestSecurityManager ();
System.setSecurityManager(sm);
try {
Example.main(args);
//should throw
fail("Should have thrown exception");
} catch (SecurityException se) {
}
assertEquals(expectedErrorMessage, outContent.toString());
}
}
Upvotes: 2
Reputation: 2621
Remove the System.exit(1) call, you don't need it. Your app will exit after main() completes anyway without an unneeded call to explicitly terminate the VM. This call is most likely causing your JUnit to stop executing before you get to your assertEquals statement, because you just told the VM to quit.
Upvotes: 0