如何测试使用Random()但不能选择相同数字两次的方法

Fan*_*eka 1 java testing random mockito

我正在创建一个小的Java游戏,它从一个原始数据(使用Random().nextInt())类型列表中随机选择,并询问哪个类型更大(或者它们是否相同).我也做了这样,如果选择相同的原始数据类型,则random.nextInt()再次调用以确保选择不同.

我现在的麻烦在于测试代码的工作原理.下面是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;

}
Run Code Online (Sandbox Code Playgroud)

我已经和Mockito一起编写了一个测试类,但是我不确定我是否正确地嘲笑是因为骰子滚动输出相同的数字而通过测试.另外,如果我将Random.nextInt()的输出模拟为特定的,这不会创建一个无限循环,因为它寻找不同的数字?

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());


}
Run Code Online (Sandbox Code Playgroud)

编辑:经过多次搜索,我被建议在GameRunner中注入一个Picker接口,可以换出测试选择器,输出固定的选择.我还创建了一个Picks类来负责选择Primitive数据类型.这一点运作良好,完全消除了使用模拟框架的需要.

fixedPrimitivePicker使用集的堆栈PrimitiveDataTypes,弹出的关闭PrimitiveDataType,每次它的对象

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());

}



}
Run Code Online (Sandbox Code Playgroud)

和精选班:

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;
}


}
Run Code Online (Sandbox Code Playgroud)

如果你想看到项目的其余部分,可以在这里找到:

https://github.com/fane247/LearningGames2

Jan*_*son 5

您可以使用Chained stubbing为您的测试添加多样性,这样您就不会使用随机返回始终相同的数字进行测试.

 when(randomNumberMock.nextInt())
   .thenReturn(4)
   .thenReturn(12);
Run Code Online (Sandbox Code Playgroud)

您也可以参数化您的测试.以下是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);
} 
Run Code Online (Sandbox Code Playgroud)

JUnit具有与参数化测试类似的功能.

编辑:模拟方法必须

nextInt(anyInt())

因为你正在调用nextInt(int bound)而不是nextInt().

when(randomNumberMock.nextInt(anyInt())
   .thenReturn(4)
   .thenReturn(12);
Run Code Online (Sandbox Code Playgroud)