Randomness Mocking With JMockit01 Apr 2016
If you had already tried to cover same bigger part of your code with JUnit tests, you have probably encountered it. With JUnit we can run tested code with predefined input and check output of it. But what if this code use, on background without control of calling code, same objects, which provide non-deterministic or changing output, like random numbers generator or real time source? How can we cover such code with tests? This can be solved using mocking.
Mocking is creating fake objects, which will act role of the object, which we want to get out of the test. Such a fake objects will be spoofed on place it and tested code will use within our test fake object instead of unpleasant real objects.
In this tutorial I will show example, how to mock most problematic classes of JDK.
At first we need to add JMockit library into us project. If you use maven, it is simple - just add following dependency:
As the second step we need to ensure that the test will be started with JMockit:
Random itself, lets try it with much simpler, but closely related, subject - mocking of system time.
We will prepare mock of
System class - here we would like to ensure constant “current” time:
Just note - for mocking of
SecureRandom is not mocking of system time required. But it is not only example too - if you want to mock
Random, it is likely you will want to mock the system time too.
Similar mock as for the
System class we will prepare to mock the
Random class. But it can cause problems in same algorithms (like key generation), where returning of constant “random” values everytime would cause getting stuck in infinite loop. We will keep pseudorandomicity of the
Random output, but we will ensure that it will return the same pseudorandom sequence on every test run. Following code will replace seed (from which the pseudorandom numbers are generated) on every new instance of
We will keep all methods of
Random untouched - they generate random values based on the seed, which is what we want.
If we would like to mock the
SecureRandom too, we just replace it with non-secure
Random, which is already mocked:
Other methods of
SecureRandom use this method to obtain the random values, so we can keep them as they are.
To start use defined mock classes we have to create new instances of them. In JUnit we can use method with
@BeforeClass annotation to ensure start using them before every test run:
The tests alone will look as usual, just mocked classes will provide mocked output:
The complete example of above you can found in gist.