Answers:
扩大大卫的回答就是我完全同意你应该创建随机的包装一致。之前,我在一个类似的问题中就此问题写了几乎相同的答案,因此这里是它的“悬崖笔记版本”。
您应该做的是首先将包装器创建为接口(或抽象类):
public interface IRandomWrapper {
int getInt();
}
具体的类如下所示:
public RandomWrapper implements IRandomWrapper {
private Random random;
public RandomWrapper() {
random = new Random();
}
public int getInt() {
return random.nextInt(10);
}
}
说您的班级如下:
class MyClass {
public void doSomething() {
int i=new Random().nextInt(10)
switch(i)
{
//11 case statements
}
}
}
为了正确使用IRandomWrapper,您需要修改类以使其成为成员(通过构造函数或setter):
public class MyClass {
private IRandomWrapper random = new RandomWrapper(); // default implementation
public setRandomWrapper(IRandomWrapper random) {
this.random = random;
}
public void doSomething() {
int i = random.getInt();
switch(i)
{
//11 case statements
}
}
}
现在,您可以通过模拟包装器来使用包装器测试类的行为。您可以使用模拟框架来执行此操作,但这也很容易自己完成:
public class MockedRandomWrapper implements IRandomWrapper {
private int theInt;
public MockedRandomWrapper(int theInt) {
this.theInt = theInt;
}
public int getInt() {
return theInt;
}
}
由于您的班级期望看起来像的东西,因此IRandomWrapper
您现在可以使用模拟的东西来强制测试中的行为。以下是一些JUnit测试的示例:
@Test
public void testFirstSwitchStatement() {
MyClass mc = new MyClass();
IRandomWrapper random = new MockedRandomWrapper(0);
mc.setRandomWrapper(random);
mc.doSomething();
// verify the behaviour for when random spits out zero
}
@Test
public void testFirstSwitchStatement() {
MyClass mc = new MyClass();
IRandomWrapper random = new MockedRandomWrapper(1);
mc.setRandomWrapper(random);
mc.doSomething();
// verify the behaviour for when random spits out one
}
希望这可以帮助。
您具有指定的范围(0-10)和指定的粒度(整数)。因此,在测试时,您无需使用随机数进行测试。您在一个循环中进行测试,该循环依次击中每种情况。我建议将随机数传递到包含case语句的子函数中,该子函数允许您仅测试该子函数。
您可以使用PowerMock库模拟Random类,并将其nextInt()方法存根以返回期望的值。如果您不想的话,无需更改原始代码。
我正在使用PowerMockito,并且刚刚测试了一种与您相似的方法。对于您发布的JUnit测试代码应如下所示:
@RunWith(PowerMockRunner.class)
@PrepareForTest( { Random.class, ClassUsingRandom.class } ) // Don't forget to prepare the Random class! :)
public void ClassUsingRandomTest() {
ClassUsingRandom cur;
Random mockedRandom;
@Before
public void setUp() throws Exception {
mockedRandom = PowerMockito.mock(Random.class);
// Replaces the construction of the Random instance in your code with the mock.
PowerMockito.whenNew(Random.class).withNoArguments().thenReturn(mockedRandom);
cur = new ClassUsingRandom();
}
@Test
public void testSwitchAtZero() {
PowerMockito.doReturn(0).when(mockedRandom).nextInt(10);
cur.doSomething();
// Verify behaviour at case 0
}
@Test
public void testSwitchAtOne() {
PowerMockito.doReturn(1).when(mockedRandom).nextInt(10);
cur.doSomething();
// Verify behaviour at case 1
}
(...)
如果您想在交换机上添加更多案例,也可以对nextInt(int)调用进行存根以接收任何参数:
PowerMockito.doReturn(0).when(mockedRandom).nextInt(Mockito.anyInt());
漂亮,不是吗?:)
使用QuickCheck!我最近才刚开始玩这个游戏,真是太神奇了。像大多数很酷的想法一样,它来自Haskell,但基本思想是让随机数生成器为您构建它们,而不是给您预先安装的测试用例。这样,您可以让计算机尝试数百或数千个输入,然后查看哪些不符合您设置的规则,而不是xUnit中可能出现的4-6种情况。
同样,QuickCheck在发现失败的案例时会尝试简化它,以便它可以找到最简单的失败案例。(当然,当您发现失败的案例时,也可以将其构建到xUnit测试中)
Java似乎至少有两个版本,因此该部分应该没有问题。