I wanted to document a test with junit and I wanted to try a simple method. The method to test reads an integer and returns it. If the value is not an integer, it catches the Exception and makes a new request until the desired value is found.
public static int leerInteger(){
int d=0;
boolean flag=false;
Scanner entrada=new Scanner(System.in);
do{
try{
System.out.println("Inserte un entero");
d=entrada.nextInt();
flag=true;
}
catch(InputMismatchException e){
System.out.println("Error en la inserción");
entrada.nextLine();
}
} while(!flag);
return d;
}
The result of the test in which a method has been used assertEquals()
is failed. When performing the test, the system does not stop after the use of Scanner in the way it would using the method to be tested, but it returns a null
directly and obviously the expected result, 0 is not the same as the one obtained, null
. And, could someone tell me what is necessary for the result to be satisfactory if the method to be tested receives an integer?
public class IO_ESTest {
public IO_ESTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of leerInteger method, of class IO_ES.
*/
@Test
public void testLeerInteger_0args() {
System.out.println("leerInteger");
int expResult = 0;
int result = IO_ES.leerInteger();
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to
//fail.
//fail("The test case is a prototype.");
}
}
JUnit is used for automated unit tests, and as such is not meant to be left waiting for the user to enter a value on stdin.
I suspect that what junit does by default is to close the standard input ( stdin ) and that's why it returns null .
There are several options to fix it:
java.lang.System.setIn(InputStream)
There is a method in java.lang.System that allows you to assign an instance of InputStream. You pass it an instance that implements the methods you're going to use and returns the expected values, and voila. It can be considered a mockup , and in fact you can probably create one with one of the required mockup frameworks .
Inject a wrapper
Your method doesn't directly use System.in but an instance of your class, which you pass to it (by constructor, setter, as parameter, etc). The usual implementation calls System.in , but for testing you use another implementation that doesn't use System.in .
This system and the former could be considered to be equivalent, with the latter a bit more "formal"
Make your logic independent of the UI.
If you have a method that adds two numbers, take the logic of asking the numbers out of the method. Simply have your method accept the two numbers as parameters and run the logic. In your program, you get the numbers from stdin and pass them to the method, from the junit you pass two fixed values and then verify that the result works.
In general, I would recommend this system, since it is more elegant, simple, and allows you to have more flexible logic (you can use the same method if the numbers come from a GUI, for example).
In your specific case, options 1 or 2 would work. In any case, be aware that the idea of unit tests is to test only your logic, regardless of the rest of the system, and that is complicated with the example you show, since there is not much to test except that you put mockups of System.in . It almost sounds like you're testing the logic of nextInt more , and that's not what is intended.
If you are just starting out, I would recommend that you try more "logical" methods, without a user interface, to get familiar.