Reputation: 907
I have a method as follows.
public static ArrayList<CustomDrinkIngredient> getCustomDrinkIngredient() {
ArrayList<CustomDrinkIngredient> customDrinkList = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
String userInput;
System.out.println("Please input ingredients per line with their quantity seperated by a comma. (q to quit)");
while (true) {
userInput = scanner.nextLine();
// Reread input if its empty, greater than 1 character or invalid
if (userInput.isEmpty()) {
System.out.println("Input is empty");
continue;
}
if (userInput.charAt(0) == 'q')
break;
String[] input = userInput.split(",");
if (input.length != 2) {
System.out.println("Input is invalid");
continue;
}
if (Ingredient.contains(input[0].toUpperCase()) == false) {
System.out.println("Ingredient is invalid");
continue;
}
// Refactor with apache commons
input[1] = input[1].trim();
if (isNumeric(input[1]) == false) {
System.out.println("Ingredient quantity is not numeric.");
continue;
}
if (!(Integer.parseInt(input[1]) > 0 && Integer.parseInt(input[1]) < 10)) {
System.out.println("Ingredient quantity is invalid. Should be less than 10.");
continue;
}
customDrinkList.add(
new CustomDrinkIngredient(Ingredient.valueOf(input[0].toUpperCase()), Integer.parseInt(input[1])));
}
scanner.close();
return customDrinkList;
}
The error checking is broken down logically within this method. However, in case of errneous data, it just prints on the console and reiterates i.e no exception thrown or true/false return.
Now if i want to unit test this, on different input scenarios, I just have the general getCustomDrinkIngredient() method to interact with as a whole.
I can simulate the System.in in my unit test as follows, passing an invalid input, but all I will get in return is an output on the screen.
@Test
public void testGetCustomDrinkIngredient() {
String data = "Coffee, 1\nInvalidInput, 1\nq";
InputStream stdin = System.in;
try {
System.setIn(new ByteArrayInputStream(data.getBytes()));
Scanner scanner = new Scanner(System.in);
ArrayList<CustomDrinkIngredient> ingredients = BaristamaticTest.getCustomDrinkIngredient();
scanner.close();
} finally {
System.setIn(stdin);
}
}
I thought of checking the arraylist for null as a mark of failure, but, that would not pinpoint which exact scenario it failed on.
How can i create unit tests for each individual scenario?
Upvotes: 0
Views: 77
Reputation: 497
Consider changing the function declaration to the following:
public static ArrayList<CustomDrinkIngredient> getCustomDrinkIngredient(
ArrayList<CustomDrinkIngredient> customDrinkList,
PrintStream out,
String userInput) { ... your code ...}
This will allow you to unit test all the scenarios about what is outputted and what the customDrinkList contains. You just pass in the objects that you will make assertions about after calling the function. In your production code there would be a function responsible for the looping over user input and calling this function with an ArrayList your accumulating ingredients in and 'System.out' plus the real user input.
Upvotes: 1