I'm currently unit testing some code to save and restore data for a game. My current save files are just text files. My unit tests save files, then load them and compare the results to the original.
Right now I'm having issues on several of the tests where Java's Scanner class, which I'm using to read the save files, will return the empty string when the line of the file its reading is not empty. After returning "", the scanner doesn't move to the next line, it instead reads the line it should have read when it returned "". My code expects an int, but it reads a string from the file instead, and throws an exception.
The example is an ItemContainer class (like a backpack for the player). The code calls a loop to load each item contained in the ItemContainer, and it successfully loads the first item, then this bug shows itself on the second iteration of the loop.
public class UnitTest {
@Test
public void testItemContainerContainsCorrectItemsAfterSaveLoad(){
try {
ItemContainer saved = Inventory.getStartingBackpack();
Weapon wpn1 = new Weapon(1, 1, 1, 1);
wpn1.description = "this is weapon number one";
wpn1.name = "weapon one";
Weapon wpn2 = new Weapon(2, 2, 2, 2);
wpn2.name = "weapon two";
wpn2.description = "this is weapon number two";
WornItem clothing = new WornItem(10, 10, 10, 2, 0);
clothing.name = "clothing";
clothing.description = "this is clothing";
saved.addItem(wpn1);
saved.addItem(wpn2);
saved.addItem(clothing);
PrintWriter writer = new PrintWriter(filePath);
saved.saveToFile(writer);
writer.close();
Scanner scanner = new Scanner(new File(filePath));
ItemContainer loaded = ItemContainer.loadAlpha0_1(scanner);
scanner.close();
Field field = ItemContainer.class.getDeclaredField("items");
field.setAccessible(true);
ArrayList<Item> savedItems = ((ArrayList<Item>) field.get(saved));
ArrayList<Item> loadedItems = ((ArrayList<Item>) field.get(loaded));
for (Item item : savedItems){
assertTrue(loadedItems.contains(item));
}
} catch (FileNotFoundException e) {
fail("threw exception");
} catch (NoSuchFieldException e) {
fail("threw exception");
} catch (SecurityException e) {
fail("threw exception");
} catch (IllegalArgumentException e) {
fail("threw exception");
} catch (IllegalAccessException e) {
fail("threw exception");
}
}
}
public class ItemContainer {
public static ItemContainer loadAlpha0_1(Scanner scanner){
int concealmentHits, concealability, spaceUsed, weightContained, baseSpace, baseWeight;
String name = scanner.nextLine();
concealmentHits = scanner.nextInt();
concealability = scanner.nextInt();
spaceUsed = scanner.nextInt();
weightContained = scanner.nextInt();
baseSpace = scanner.nextInt();
baseWeight = scanner.nextInt();
ArrayList<Item> items = loadItemsAlpha0_1(scanner);
return new ItemContainer(baseWeight, baseSpace, name, items);
}
private static ArrayList<Item> loadItemsAlpha0_1(Scanner scanner) {
ArrayList<Item> items = new ArrayList<Item>();
// scanner.nextLine();
// This is my bandaid fix for an unexplained blank line "" that keeps being read
// at certain points in the code.
scanner.nextLine();
String itemType = scanner.nextLine();
while(!itemType.equals("end item container")) {
Item item = Item.loadAlpha0_1(scanner, itemType);
items.add(item);
itemType = scanner.nextLine(); // this line is when the bug mentioned shows up
}
return items;
}
}
public class Weapon extends Item {
public static Weapon loadAlpha0_1(Scanner scanner) {
int size, weight, durability, hardness, damage, weaponType, parry, accuracy, might;
String name = scanner.nextLine();
size = scanner.nextInt();
weight = scanner.nextInt();
durability = scanner.nextInt();
hardness = scanner.nextInt();
damage = scanner.nextInt();
String description = Item.loadItemDescriptionAlpha0_1(scanner);
weaponType = scanner.nextInt();
parry = scanner.nextInt();
accuracy = scanner.nextInt();
might = scanner.nextInt();
Weapon weapon = new Weapon(size, weight, durability, hardness, damage,
weaponType, parry, accuracy, might);
weapon.name = name;
weapon.description = description;
return weapon;
}
}
this is the file that is being read during the test
backpack
0
0
50
50
1000
10
weapon
weapon one
15
15
125
5
0
this is weapon number one
end description
1
1
1
1
weapon
weapon two
25
25
150
5
0
this is weapon number two
end description
2
2
2
2
worn item
clothing
10
10
10
2
0
end item container
I know it's a lot of code to share, but I've been trying to figure this out for a very long time and I haven't been able to.
Edit: I found a bug that I created while messing around and trying to debug this. I've corrected it.