Расширяя ответ Дэвида, с которым я полностью согласен, вы должны создать оболочку для Random. Я написал примерно такой же ответ об этом ранее в аналогичном вопросе, так что вот «версия заметок Клиффа».
Что вы должны сделать, это сначала создать оболочку как интерфейс (или абстрактный класс):
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, вам нужно изменить класс так, чтобы он воспринимался как член (через конструктор или установщик):
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, должен выглядеть примерно так:
Вы также можете заглушить вызов nextInt (int) для получения любого параметра, если вы хотите добавить больше дел в свой коммутатор:
Довольно, не правда ли? :)
источник
Используйте QuickCheck ! Я только начал играть с этим недавно, и это удивительно. Как и большинство классных идей, оно исходит от Haskell, но основная идея заключается в том, что вместо того, чтобы давать тесты заранее подготовленным тестам, вы позволяете генератору случайных чисел создавать их для вас. Таким образом, вместо 4-6 случаев, которые вы, вероятно, придумали в xUnit, вы можете заставить компьютер попробовать сотни или тысячи входов и посмотреть, какие из них не соответствуют установленным вами правилам.
Также QuickCheck будет при обнаружении сбойного случая попытаться упростить его, чтобы найти простейший возможный сбой. (И, конечно, когда вы обнаружите сбойный случай, вы можете также встроить его в тест xUnit)
Похоже, что для Java существует как минимум две версии, поэтому эта часть не должна быть проблемой.
источник