Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking SecureRandom::nextInt()

I have a class that uses a SecureRandom instance and grabs the next random number.

Lets say the example is:

public class ExampleClass() {
   public void method() { 
      Random sr = new SecureRandom();
      System.out.printf("%d %n", sr.nextInt(1));
      System.out.printf("%d %n", sr.nextInt(1));
   }
}

Test code

@RunWith(PowerMockRunner.class)
public class ExampleClassTest {
...
@Test
@PrepareOnlyThisForTest(SecureRandom.class)
public void mockedTest() throws Exception {

    Random spy = PowerMockito.spy(new SecureRandom());

    when(spy, method(SecureRandom.class, "nextInt", int.class))
            .withArguments(anyInt())
            .thenReturn(3, 0);


    instance.method();
}

When I am attempting to run the unit test, the unit test ends up freezing. When I attempt to debug only that method, JUnit reports back that the test isn't a member of the class.

No tests found matching Method mockedTest(ExampleClass) from org.junit.internal.requests.ClassRequest@6a6cb05c 

EDIT: Moving @PrepareOnlyThisForTest to PerpareForTests to the top of the class fixed the freezing issue. However I'm getting the problem that the method isn't being mocked.

like image 391
monksy Avatar asked Sep 19 '25 00:09

monksy


1 Answers

Try using @PrepareForTest at the class level of your test, not at method level.

@RunWith(PowerMockRunner.class)
@PrepareForTest(SecureRandom.class) 
public class ExampleClassTest {
...
}

Edit: In order to invoke the mock, you need to do the following:

1) Add the ExampleClass to the PrepareForTest annotation:

@RunWith(PowerMockRunner.class)
@PrepareForTest({SecureRandom.class, ExampleClass.class}) 
public class ExampleClassTest {
...
}

2) Mock the constructor call for SecureRandom:

SecureRandom mockRandom = Mockito.mock(SecureRandom.class);
PowerMockito.whenNew(SecureRandom.class).withNoArguments().thenReturn(mockRandom);

A working example is given below:

@RunWith(PowerMockRunner.class)
@PrepareForTest({SecureRandom.class, ExampleClass.class})
public class ExampleClassTest {

    private ExampleClass example = new ExampleClass();

    @Test
    public void aTest() throws Exception {

        SecureRandom mockRandom = Mockito.mock(SecureRandom.class);
       PowerMockito.whenNew(SecureRandom.class).withNoArguments().thenReturn(mockRandom);
        Mockito.when(mockRandom.nextInt(Mockito.anyInt())).thenReturn(3, 0);
        example.method();
   }
}
like image 63
JamesB Avatar answered Sep 20 '25 14:09

JamesB