I am writing a unit test for a function and in the real function I have:
rng = default_rng()
...
... # a little while later
while N<50:
...
idx = rng.integers(100)
How do I mock out either the variable idx or the call to rng.integers? In other words, I'd like to make idx pull from a simple ordered list [0, 1, 2, ...].
Every time I try @mock.patch('numpy.random.default_rng', side_effects=[0, 1, 2, ...])
decorating the test function, the code 'runs' but doesn't do what I am hoping. If I replace the above to 'numpy.random.default_rng.integers I get an error that says default_rng has no attribute integers (I believe bc it is a generator object). I've tried a number of different iterations using @mock.patch.object but still to no avail.
There are some problems with your patching. First, you are obviously using from numpy.random import default_rng
, so you have to patch the default_rng
instance in your module - see where to patch.
Second, integers
is called on the instance of default_rng
, not on the class, so you first have to get the instance of the mock, with is done via return_value
.
And third: it's called side_effect
, not side_effects
(though that may just be a typo in your question).
So a working version could look like this (adapted a bit to actually be able to test something):
sut.py
from numpy.random import default_rng
def get_random():
rng = default_rng()
idx = 0
while idx < 50:
idx = rng.integers(100)
return idx
test_sut.py
@mock.patch('sut.default_rng')
def test_get_random(mocked):
mocked.return_value.integers.side_effect = range(60)
assert do_something() == 50