Issue
I have the following variables in a TableService class and a function which takes currentPlayer index on the list, adds +1 and make currentPlayer the one with this incremented index.
currentPlayer is assigned as currentPlayer = Optional.of(players.get(0));
earlier in different method.
private ArrayList<Player> players = new ArrayList<>();
private Optional<Player> currentPlayer = Optional.empty();
public void setNextPlayerCurrent() {
int currentPlayerIndex = players.indexOf(currentPlayer.get());
if (!lastPlayerCheck(currentPlayerIndex)) {
currentPlayer = Optional.of(players.get(currentPlayerIndex + 1));
}
else {
currentPlayer = Optional.of(players.get(0));
}
}
I want to test this and I wrote the following function:
@Test
void checkCurrentPlayerSetting() {
List<Player> players = tableService.getPlayers();
Optional<Player> currentPlayer = tableService.getCurrentPlayer();
Player player1 = new Player("A", "Adam", 100);
Player player2 = new Player("B", "Bella", 100);
players.add(player1);
players.add(player2);
currentPlayer = Optional.of(players.get(0));
int player1Index = players.indexOf(player1);
int player2Index = players.indexOf(player2);
System.out.println(player1Index); // prints 0
System.out.println(player2Index); / prints 1
System.out.println(players.indexOf(currentPlayer.get())); // prints 0
tableService.setNextPlayerCurrent(); // java.util.NoSuchElementException: No value present!!!
//assertEquals(player2.getId(), currentPlayer.get().getId());
}
I want to assert that after execution of setNextPlayerCurrent() player2 will match currentPlayer. What should I do with the exception?
EDIT: lastPlayerCheck() also in the TableService class:
public boolean lastPlayerCheck(int currentPlayerIndex) {
if (currentPlayerIndex == (players.size() - 1)) {
return true;
}
return false;
}
Solution
As far as I can tell the currentPlayer
field in the TableService
was never assigned a different value other than being initialized with Optional.empty()
. Therefore, your TableService
maybe needs a method like setCurrentPlayer(Player player)
so you can manually configure the currentPlayer
field. Note: The way you try to assign a value to the currentPlayer
field in the test does not work!
// here you only get a reference to the currently empty Optional object
Optional<Player> currentPlayer = tableService.getCurrentPlayer();
// here you just assign the variable (which is only visible in the context of this test)
// to a fresh Optional holding an actual player object - this has no effect on the
// currentPlayer field inside the TableService
currentPlayer = Optional.of(players.get(0));
Maybe your next thought is to do something like this:
Optional<Player> currentPlayer = tableService.getCurrentPlayer();
currentPlayer.setValue(players.get(0)) // WILL NOT COMPILE
But Java Optionals are IMMUTABLE meaning that you can not assign a new value to an Optional Object, but instead you have to create a new Optional
object with the value you want to assign. This is why there is no method such as setValue()
in the Optional
class.
UPDATE: I think you are not yet fully understanding how method parameters function. What you are basically trying to do is:
void updateString(String: someString){
someString = "updated string value"
}
String someString = "initial string value"
updateString(someString)
println(someString) // => will still be "initial string value"
When you pass a variable as an argument to a method you can not reassign that variable in the context of the method, so that the variable outside the method (from where this method was invoked) is also reassigned! Actually the someString
parameter in the updateString(String: someString)
method is a different variable than the someString
variable in the outer scope (from where the method was invoked) but only holds the reference to the same value ("updated string value" in this case). So when you reassign that variable in the inner method you are not updating the variable (in the outer scopee) that has been passed into the method!
Answered By - inoflow
Answer Checked By - Cary Denson (JavaFixing Admin)