Randomock is a mocking library for the standard library rand package.
I was writing some simulation software that heavily utilized the rand package functions and found that it was difficult to write tests for most of my code. Since the standard library rand package only provides functions and no interfaces, mocking the results of calls to the rand package was more of a pain than it needed to be.
Randomock provides the Randomizer
interface, which describes two of the main structs in the package:
Random
- A thin wrapper around stdlib rand
package functions. This is meant to be used in your non-test code.
RandoMock
- Mocked version of Random
which allows you to specify the return values for certain function calls.
One of the main differences to using the Randomizer
interface is that all calls must be given a key.
In the case of RandomMock
, this key is used to keep track of which values to return. For Random
, the key
does nothing.
In your test code, create an instance of RandoMock:
r := NewRandoMock()
Then add the mocked return values for a certain key:
r.Add("dice", 4)
or, add many return values for a key at the same time:
r.Add("dice", 4, 3, 1)
This will cause any call to a rand method to turn 4
the first time, 3
the second time and 1
the third time.
For convenience, keys with only one return value always return that value no matter how many times they are called.
For keys which have more than one return value, the values will be returned in the order they were added.
When called more times than there are return values, the RandoMock
's policy defines what occurs.
The default policy is set to ErrorOutPolicy
, which means the code will panic when called more times than there are
return values. This is the safest solution as it will immediately indicate that you have not set up your
tests with enough mock return values.
You can change the default policy with SetDefaultPolicy(p Policy)
or the policy of individual RandoMock instances
with the SetPolicy(key string, p Policy)
method.
WrapAroundPolicy - When all return values are exhausted, start again from the first value.
RepeatLastPolicy - When all return values are exhausted, repeat the last return value.
ErrorOutPolicy - When all return values are exhausted, panic on the next call.
In your non-test code, simply create a Random
instance and hold it inside of a Randomizer
interface.
var r randomock.Randomizer = &randomock.Random{}
You can now call all your rand
functions through this object.
r.Int("roll")
r.Float64("age")
r.ExpFloat64("norm")
Use a randomock.RandoMock instance in your Randomizer interface instead. Before calling your test, load up the mock return values and set the policy (if required).
var r randomock.Randomizer = randomock.NewRandoMock().Add("roll", 2.0, 3.0, 5.0, 2.0)
See the example directory for examples of how to use randomock in your tests.
Feel free to open a ticket if you find any issues or would like to request a feature. PR's are also welcome.