How do you mock behavior for methods that depend on randomness (like Math.random())?

Testing code that depends on randomness, like Math.random(), requires isolating the random source behind an interface so it can be mocked and given deterministic values in tests.

Key Points: • Wrap Math.random() (or java.util.Random) inside a small class, e.g. RandomGenerator, that your production code depends on via an interface. • In tests, mock that interface and stub its method with when()/thenReturn() to return a fixed value. • This makes the test deterministic and repeatable instead of relying on chance or wide assertion ranges. • The same pattern applies to any nondeterministic source - system clocks, UUID generation, or external randomness services. • Directly calling Math.random() in business logic without abstraction makes it effectively untestable with precision.

Example: A DiceRoller class calling Math.random() internally is hard to test; extracting a RandomSource.nextDouble() dependency lets a test stub it to return exactly 0.5 and assert the resulting roll is deterministic.

Code Example:

interface RandomSource {
    double nextDouble();
}

class DiceRoller {
    private final RandomSource random;
    DiceRoller(RandomSource random) { this.random = random; }
    int roll() { return (int) (random.nextDouble() * 6) + 1; }
}

@Test
void rollsPredictableValue() {
    RandomSource random = mock(RandomSource.class);
    when(random.nextDouble()).thenReturn(0.0);

    assertEquals(1, new DiceRoller(random).roll());
}

Interview Tip: A concise interview answer is:

"I abstract the random source behind a small interface, inject it into the class under test, and mock that interface to return a fixed value with when()/thenReturn(). That turns an inherently nondeterministic method into something I can assert on precisely."