Expandindo a resposta de David, com a qual concordo totalmente que você deve criar um invólucro para o Random. Eu escrevi praticamente a mesma resposta sobre isso anteriormente em uma pergunta semelhante, então aqui está uma "versão das notas de Cliff".
O que você deve fazer é primeiro criar o wrapper como uma interface (ou classe abstrata):
public interface IRandomWrapper {
int getInt();
}
E a classe concreta para isso ficaria assim:
public RandomWrapper implements IRandomWrapper {
private Random random;
public RandomWrapper() {
random = new Random();
}
public int getInt() {
return random.nextInt(10);
}
}
Digamos que sua turma seja a seguinte:
class MyClass {
public void doSomething() {
int i=new Random().nextInt(10)
switch(i)
{
//11 case statements
}
}
}
Para usar o IRandomWrapper corretamente, você precisa modificar sua classe para aceitá-la como membro (por meio de construtor ou 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
}
}
}
Agora você pode testar o comportamento da sua classe com o wrapper, zombando do wrapper. Você pode fazer isso com uma estrutura de simulação, mas isso também é fácil de fazer:
public class MockedRandomWrapper implements IRandomWrapper {
private int theInt;
public MockedRandomWrapper(int theInt) {
this.theInt = theInt;
}
public int getInt() {
return theInt;
}
}
Como sua classe espera algo parecido com um, IRandomWrapper
agora você pode usar o que é ridicularizado para forçar o comportamento em seu teste. Aqui estão alguns exemplos de testes 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
}
Espero que isto ajude.
Você pode (deve) agrupar o código de geração aleatória em uma classe ou método e depois simular / substituir durante os testes para definir o valor desejado, para que seus testes sejam previsíveis.
fonte
Você tem um intervalo especificado (0-10) e uma granularidade especificada (números inteiros). Portanto, ao testar, você não testa com números aleatórios. Você testa dentro de um loop que atinge cada caso por vez. Aconselho passar o número aleatório para uma subfunção que contém a instrução case, que permite testar apenas a subfunção.
fonte
Você pode usar a biblioteca do PowerMock para zombar da classe Random e stub seu método nextInt () para retornar o valor esperado. Não é necessário alterar o código original, se você não quiser.
Estou usando o PowerMockito e acabei de testar um método semelhante ao seu. Para o código que você postou o teste JUnit deve ser algo como isto:
Você também pode stub a chamada nextInt (int) para receber qualquer parâmetro, caso queira adicionar mais casos ao seu switch:
Bonito, não é? :)
fonte
Use o QuickCheck ! Eu comecei a brincar com isso recentemente e é incrível. Como a maioria das idéias interessantes, ela vem da Haskell, mas a idéia básica é que, em vez de fornecer aos seus casos de teste pré-enlatados, você deixe seu gerador de números aleatórios construí-los para você. Dessa forma, em vez dos 4-6 casos que você provavelmente apresentaria no xUnit, o computador pode tentar centenas ou milhares de entradas e ver quais não estão em conformidade com as regras que você definiu.
O QuickCheck também tentará simplificá-lo, quando encontrar um caso com falha, para encontrar o caso mais simples possível que falhar. (E, é claro, quando você encontra um caso com falha, pode construí-lo também em um teste xUnit)
Parece haver pelo menos duas versões para Java, para que parte não deva ser um problema.
fonte