Reputation: 569
I'm creating a little java game which randomly picks from a list of Primitive data (using Random().nextInt()
) types and asks which type is larger (or if they're both the same). I've also made it so that if the same Primitive data type is picked then random.nextInt()
is called again to ensure the selections are different.
My trouble now comes in testing that the code works. Below is the Game.class:
static final PrimitiveDataType BOOLEAN_TYPE = new PrimitiveDataType("boolean", 0);
static final PrimitiveDataType BYTE_TYPE = new PrimitiveDataType("byte", 8);
static final PrimitiveDataType SHORT_TYPE = new PrimitiveDataType("short", 16);
static final PrimitiveDataType CHAR_TYPE = new PrimitiveDataType("char", 16);
static final PrimitiveDataType INT_TYPE = new PrimitiveDataType("int", 32);
static final PrimitiveDataType LONG_TYPE = new PrimitiveDataType("long", 64);
static final PrimitiveDataType FLOAT_TYPE = new PrimitiveDataType("float", 32);
static final PrimitiveDataType DOUBLE_TYPE = new PrimitiveDataType("double", 64);
static List<PrimitiveDataType> PRIMITIVE_TYPES = Arrays.asList(BOOLEAN_TYPE, BYTE_TYPE, SHORT_TYPE, CHAR_TYPE,
INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE);
static List<PrimitiveDataType> chosenDataTypes = new ArrayList<PrimitiveDataType>();
private static int numberOfQuestions;
static Random numberGenerator = new Random();
static void setChosenDataTypeIndexs(Random numberGenerator) {
int choice1 = numberGenerator.nextInt(PRIMITIVE_TYPES.size()-1)+0;
int choice2 = numberGenerator.nextInt(PRIMITIVE_TYPES.size()-1)+0;
System.out.println("Random Roll (1) " +choice1);
System.out.println("Random Roll (2) " +choice2);
do {
choice2 = numberGenerator.nextInt(PRIMITIVE_TYPES.size()-1)+0;
} while (choice1==choice2);
Game.chosenDataTypes.add(PRIMITIVE_TYPES.get(choice1));
Game.chosenDataTypes.add(PRIMITIVE_TYPES.get(choice2));
}
static PrimitiveDataType getChosenDataTypeIndexs(int i) {
return chosenDataTypes.get(i);
}
public static void setNumberOfQuestions(int i) {
numberOfQuestions = i;
}
I've had a go with writing a testclass with Mockito, but i'm not sure if i'm mocking correctly due to getting passing test with the dice roll outputting the same number. Also, if i mock out the output of Random.nextInt() to a specific wouldn't this create an infinite loop as it looks for a different number?
public class GameTest {
@Test
public void getChosenDataTypesTest(){
Random randomNumberMock = Mockito .mock(Random.class);
when(randomNumberMock.nextInt()).thenReturn(1);
Game.setChosenDataTypeIndexs(randomNumberMock);
assertNotEquals(Game.chosenDataTypes.get(0), Game.chosenDataTypes.get(1));
verify(randomNumberMock,times(2)).nextInt();
}
@Test
public void setNumberOfQuestionsTest(){
Game.setNumberOfQuestions(1);
assertEquals(1,Game.getNumberOfQuestions());
}
EDIT: After much searching I've been advised to inject a Picker interface into the GameRunner which can be swapped out for test Picker which outputs fixed picks. I've also created a Picks Class to be responsible for picking the Primitive data types. this has worked well and eliminated the need for using a mocking framework entirely.
The fixedPrimitivePicker
uses a stack of set PrimitiveDataTypes
that pop's off PrimitiveDataType
Objects each time it
package org.FaneFonseka.LearningGames2;
import org.junit.Before;
import org.junit.Test;
import java.util.Stack;
/**
* Created by Fane on 23/12/2016.
*/
public class PicksTest {
private Picks picks;
private Picker fixedPrimitivePicker;
private Stack<PrimitiveDataType> primitiveDataTypeStack;
private PrimitiveDataType primitive1;
private PrimitiveDataType primitive2;
private PrimitiveDataType primitive3;
@Before
public void setup() {
primitiveDataTypeStack = new Stack<PrimitiveDataType>();
primitiveDataTypeStack.push(primitive3 = new PrimitiveDataType("int", 32));
primitiveDataTypeStack.push(primitive2 = new PrimitiveDataType("boolean", 1));
primitiveDataTypeStack.push(primitive1 = new PrimitiveDataType("boolean", 1));
fixedPrimitivePicker = new Picker() {
public PrimitiveDataType pick() {
return primitiveDataTypeStack.pop();
}
};
picks = new Picks(fixedPrimitivePicker);
}
@Test
public void setFirstPickTest() {
picks.setPicks();
assert picks.getFirstPick().equals(primitive1);
}
@Test
public void setSecondPickTest() {
picks.setPicks();
assert picks.getSecondPick().equals(primitive3);
}
@Test
public void secondPickIsDifferentFromFirstPickTest() {
picks.setPicks();
assert !picks.getFirstPick().equals(picks.getSecondPick());
}
}
and the Picks Class:
package org.FaneFonseka.LearningGames2;
class Picks {
private PrimitiveDataType firstPick;
private PrimitiveDataType secondPick;
private Picker randomPrimitivePicker;
Picks(Picker randomPrimitivePicker) {
this.randomPrimitivePicker = randomPrimitivePicker;
}
boolean firstPickGreaterThanSecondPick() {
System.out.println(getFirstPick().getMemorySizeInBits() > getSecondPick().getMemorySizeInBits());
return getFirstPick().getMemorySizeInBits() > getSecondPick().getMemorySizeInBits();
}
boolean secondPickGreaterThanFirstPick() {
System.out.println(getFirstPick().getMemorySizeInBits() < getSecondPick().getMemorySizeInBits());
return getFirstPick().getMemorySizeInBits() < getSecondPick().getMemorySizeInBits();
}
boolean firstPickIsSameSizeAsSecondPick() {
System.out.println(getFirstPick().getMemorySizeInBits() == getSecondPick().getMemorySizeInBits());
return getFirstPick().getMemorySizeInBits() == getSecondPick().getMemorySizeInBits();
}
void setPicks() {
setFirstPick(randomPrimitivePicker);
setSecondPick(randomPrimitivePicker);
}
private void setFirstPick(Picker randomPrimitivePicker) {
this.firstPick = randomPrimitivePicker.pick();
}
PrimitiveDataType getFirstPick() {
return this.firstPick;
}
private void setSecondPick(Picker randomPrimitivePicker) {
PrimitiveDataType pick;
do {
pick = randomPrimitivePicker.pick();
} while (pick.equals(firstPick));
this.secondPick = pick;
}
PrimitiveDataType getSecondPick() {
return secondPick;
}
}
If you want to see the rest of the project it can be found here:
https://github.com/fane247/LearningGames2
Upvotes: 2
Views: 14156
Reputation: 4841
You can add variety to your test with Chained stubbing, so that you are not testing with random returning always same number.
when(randomNumberMock.nextInt())
.thenReturn(4)
.thenReturn(12);
You could also parameterize your test. Here is example for TestNG.
@DataProvider()
public static Object[][] randomNumbers() {
return new Object[][] {{2, 3}, {6, 7}, {19, 15}};
}
@Test(dataProvider = "random")
public void getChosenDataTypesTest(int first, int second) {
when(randomNumberMock.nextInt())
.thenReturn(first)
.thenReturn(second);
}
JUnit has similar feature for parameterized tests.
EDIT: Mocked method has to be
nextInt(anyInt())
because you are calling nextInt(int bound) not nextInt().
when(randomNumberMock.nextInt(anyInt())
.thenReturn(4)
.thenReturn(12);
Upvotes: 6