2

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

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
Fane Fonseka
  • 549
  • 2
  • 5
  • 7

1 Answers1

6

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);
Januson
  • 4,533
  • 34
  • 42
  • When i use the when(randomNumberMock.nextInt()) .thenReturn(4) .thenReturn(12); method the test goes into an infinite loop where both dice rolls are 0? – Fane Fonseka Nov 25 '16 at 11:20
  • See the edit. We were mocking wrong method. Mocked method was nextInt() but code called nextInt(int bound) which was returning 0. – Januson Nov 25 '16 at 12:23
  • Also your verify check will fail, because you are always calling anyInt at least three times. do-while does the condition check after first loop. – Januson Nov 25 '16 at 12:27
  • Good spot this is now calling the correct numbers. However, I want to check the logic within setChosenDataTypeIndexs(). Namely, if the same number is chosen by the random number generator it calls until the number is different. Do you know how I can go about this? – Fane Fonseka Nov 25 '16 at 13:38
  • Just use "while (choice1==choice2) { ... }" This way it will check first and generate new value only if they are the same. – Januson Nov 25 '16 at 13:53
  • not sure if this is a null point but I already have this bit of code in the Game.class file. Do I need to create test to create a scenario when two numbers that are the same are chosen as choices to test this or is it not necessary? – Fane Fonseka Nov 25 '16 at 15:40
  • What I meant is that you can get rid of redundant random call in Game class. Check the difference between the while loop and the do-while loop. See links below. https://docs.oracle.com/javase/tutorial/java/nutsandbolts/while.html http://stackoverflow.com/questions/20044845/do-while-and-while-comparison – Januson Nov 27 '16 at 08:41