I have a method which is a part of the interface I am implementing. This method calls another private method which uses a random number generator to produce output and returns it to the calling method. I want to test the calling method. How can I do that? This is the method under test:

 public String generate(int wordCount) {
    StringBuilder sentence = new StringBuilder();

    List<String> selectedStrings = selectRandomStringsFromInternalVocabulary(wordCount, new Random());


    for (String word: selectedStrings)
                .append(" ");

    return sentence.toString().trim();

This is the method that uses random number generator:

private List<String> selectRandomStringsFromInternalVocabulary(int wordCount, Random random) {
    List<String> selectedStrings = new ArrayList<>();
    int wordCountInVocabulary = internalVocabulary.size();

    while (wordCount-- != 0) {
        int stringIndex = random.nextInt(wordCountInVocabulary);

    return selectedStrings;

There are a few things that I've thought I can do: 1. Make the second method package-private and test it. But I don't want to test a private method if I can avoid it. 2. Add Random as a parameter to the calling function and pass a mock during test. However, its part of the interface and other classes implementing it does not use RNG. Furthermore, I don't want clients to know about the implementation details.

I have gone through these questions: 1. Unit testing methods with indeterminate output 2. Unit Testing a function with random behavior

But the suggestions are similar to what I mentioned above.

  • 3
    Possible duplicate of How should I test randomness?
    – gnat
    Commented Aug 29, 2017 at 9:45
  • Remarks about question duplication belong in the comments, not in your question. Commented Aug 29, 2017 at 16:07
  • I don't think there's a need to create a new Random every time there. Have a Random as an instance member.
    Commented Aug 30, 2017 at 6:58
  • You should be looking at mathematical proofs, not tests. The tests are simply a backup as they prove nothing. Commented Aug 30, 2017 at 22:26
  • I'm not trying to test whether the randomness of the selected strings conform strictly to some statistical distribution. I'm trying to test 1. the selected strings are not the same every time 2. odd indexed strings are swapped with even indexed ones.
    – sayeed910
    Commented Aug 31, 2017 at 9:13

4 Answers 4


The question you should be asking yourself is "What am I trying to prove?" (NOTE: "prove" is not used in the mathematical sense, but simply to test the validity of something). Unit tests are there to test that your application is functioning within it's designed parameters. Different tests for correctness require different approaches:

  • You can verify that all words in the returned the string exist in the global vocabulary
  • You can verify that there are, or are no repeats of words in that returned string
  • You can verify that there is no extraneous white space at the beginning and end
  • You can verify that the number of words enforces positive numbers
  • You can verify that the a list of 0 words provides an empty string

That might be sufficient for your needs. Those types of tests are also fairly robust. They won't break if the implementation of the random number generator changes. You are still working through the external interface to get at the internal features.

I think in this case it would prove both brittle and only marginally useful to test specific sequences of strings. There aren't really that many branch paths to worry about in your example. Think about the contracts and what it is you really need to ensure, and embrace the randomness.

The important thing to note is that you are not proving randomness. You are ensuring that your method behaves as expected.

If you were testing randomness, you would need to do some statistical analysis to prove the spread of random numbers was as expected, etc. Those kinds of tests would require "proof" in the mathematical sense of the word. Unit tests aren't the right tool for that job.

  • 1
    Unfortunately unit tests can rarely "prove" anything. This answer would be good if it encouraged actual proofs, informal or formal. The proofs are more important than the tests. Commented Aug 30, 2017 at 22:24
  • 2
    If this is your opinion, perhaps you aren't writing the right tests. Of course, this could also be a case of getting hung up on the semantics of the word "proof". In either case, the tests can easily be written to prove every one of those bullet points. Perhaps you are thinking in the mathematical concept of the word. If that's the case I'll concede that I'm no mathematical genius. I'm just a guy who learned by experience it's best to embrace the randomness and test what's conceptually important. Commented Aug 30, 2017 at 23:42
  • 1
    Yes, I was using the word proof as commonly defined (mathematical proof). Informal proofs can work as well. But tests don't prove anything unless you can cover the whole state space, which is usually unrealistic. I think your answer would be fine if you did not use the word "proof" or "prove" in that way. Commented Aug 30, 2017 at 23:52
  • 1
    Just saying "you can test" instead of "you can prove", "testing" instead of "proving", would probably fix it. Commented Aug 30, 2017 at 23:54
  • 2
    Well, most things that you test are things that you want to prove, but proving is so much effort that you simply test them instead. How about using the word "ensure" instead of "prove"? Commented Aug 31, 2017 at 5:12

Use dependency injection. Create an IRandomNumberGenerator interface, and inject it into your class (as constructor argument) or function (as parameter) that needs it. It can be as simple as the following:

interface IRandomNumberGenerator
     int GetRandomNumber();

Now create two classes that implement that interface. Your real number generator class, and a mock. Your mock implementation will return a predefined number, your real implementation will return an actual random number. Test with the mock implementation.

class MockRandomNumberGenerator : IRandomNumberGenerator
     private int _fakeRandomNumber;

     public MockRandomNumberGenerator(int fakeRandomNumber)
          _fakeRandomNumber = fakeRandomNumber

     public int GetRandomNumber()
          return _fakeRandomNumber;

Under no condition test with actual random numbers being generated, your test results will no longer be reproducible in that case. I'm using C# syntax, as I'm not familiar with Java.

  • Unrelated to the question. Commented Aug 30, 2017 at 22:24
  • Seems like a lot of hassle when using the a real RNG with a specific seed, which works fine and disproves your last paragraph. Commented Aug 31, 2017 at 2:39
  • @whatsisname It works fine, until you want to ensure the test passes with a specific random number being generated. Mocking it takes 1 second (if you're not using Mocking libraries, you should), and gives you infinite flexibility.
    – Eternal21
    Commented Aug 31, 2017 at 11:37
  • @FrankHileman Which part?
    – Eternal21
    Commented Aug 31, 2017 at 11:38
  • 3
    @FrankHileman Because DI is the best way to decouple your unit under test from other responsibilities. As it is, the code was responsible both for generating random numbers, and selecting vocabulary words. That's why writing a test for it wasn't straightforward. Applying SRP (via DI) fixed that deficiency.
    – Eternal21
    Commented Aug 31, 2017 at 16:29

When testing:

Use your random number generator with a particular seed that you specify. Then you will always get the same sequence. This makes it testable.

  • Do I add the seed to production code? I don't have access to RNG in test code.
    – sayeed910
    Commented Aug 29, 2017 at 9:40
  • @sayeed That would force results to always be the same. I'm guessing that's not what you're after so no. Is there a configuration file? You could load a seed value from the configuration, and only if it is provided, set it in the program. Your production configuration would not have a seed and you can test your code in test environment with a predefined seed with no need to concern yourself of changing program functionality between test and production.
    – Neil
    Commented Aug 29, 2017 at 12:19
  • 5
    Honestly, I think this leads to brittle tests. Why not prove aspects of the methods that can be proven without worrying about specific results. Commented Aug 29, 2017 at 13:53

Make random a member of the class under test. Inject a mocked/fixed-seed value in for testing, and a real one for production code. Use Dependency injection.

class someclassname {
    private Random _rng;

    constructor(Random rng)

    public String generate(int wordCount)

    private selectRandomStringsFromInternalVocabulary(int wordCount) //words would be a better name here btw

You may want to make the vocabulary a dependency as well.

Also, you might have a bug that this will fix anyway. I don't know about Java, but going new Random() in a method that is called very frequently (say in a fast loop) can go badly when the default constructor uses a time based seed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.