I'm trying to create a Junit test for a method which is using a simple random number for calling another simple method which returns rock, paper, or scissor depending on the value of the parameter.
I don't know how to do this.
public class Play {
public String player2Choice() {
// Create a Random object.
Random random = new Random();
// Ramdon number between 1-3
int numberChoice = random.nextInt(3) + 1;
// Return the player random choice
return getItem(numberChoice);
}
public String getItem(int numberChoice) {
String item;
switch (numberChoice) {
case 1:
item = "rock";
break;
case 2:
item = "scissors";
break;
case 3:
item = "paper";
break;
default:
item = null;
}
return item;
}
}
Right now I have this test:
Play play;
@Before
public void setup() {
play = new Play();
}
@Test
public void testPlayer2Choice() {
int param = 1;
Play play2 = Mockito.mock(Play.class);
play2.getItem(param);
Mockito.verify(play2).getItem(param);
String result = play.player2Choice();
assertEquals("rock", result);
}
Play
is tightly coupled to Random
, which it really has no control over. This makes testing specific number choices difficult.
If the goal is to test that given a number choice of 1
, player2Choice
returns "rock"
then more control of the so-called randomness is needed.
public interface RandomInteger {
int nextInt(int max);
}
The implementation of the interface will encapsulate an actual Random
class and proxy the desired behavior/functionality
public class RandomIntegerImplementation : RandomInteger {
private Random random ;
public RandomIntegerImplementation() {
// Create a Random object.
random = new Random();
}
public int nextInt(int max) {
return random.nextInt(max);
}
}
Play would then need to be refactored to explicitly depend on the now abstraction random provider.
public class Play {
private RandomInteger random;
public Play(RandomInteger random) {
this.random = random;
}
public String player2Choice() {
// Ramdon number between 1-3
int numberChoice = random.nextInt(3) + 1;
// Return the player random choice
return getItem(numberChoice);
}
//...code removed for brevity
}
So now if the above stated test case is to be satisfied, the dependency can be mocked to behave as expected.
RandomInteger random;
Play play;
@Before
public void setup() {
random = Mockito.mock(RandomInteger.class);
play = new Play(random);
}
@Test
public void testPlayer2Choice_Given_Zero() {
//Arrange
String expected = "rock";
int numberChoice = 0;
when(random.nextInt(3)).thenReturn(numberChoice);
//Act
String actual = play.player2Choice();
//Assert
Mockito.verify(play).getItem(numberChoice + 1);
assertEquals(expected, actual);
}
This should be enough for a start. The same can be done for other test cases.
Eventually getItem
could also be refactored out into its own service but that is outside of the scope of the original question.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.