如何在 python 中模拟随机数生成器对象

How to mock a random number generator object in python

我正在为一个函数编写单元测试,在实际函数中我有:

rng = default_rng()
...
... # a little while later
while N<50:
    ...
    idx = rng.integers(100)

如何模拟变量 idx 或对 rng.integers 的调用?换句话说,我想让 idx 从一个简单的有序列表 [0, 1, 2, ...].

每次我尝试 @mock.patch('numpy.random.default_rng', side_effects=[0, 1, 2, ...]) 修饰测试函数时,代码 'runs' 但没有达到我的期望。如果我将上面的替换为 'numpy.random.default_rng.integers 我会收到一条错误消息,指出 default_rng 没有属性整数(我相信 bc 它是一个生成器对象)。我已经使用@mock.patch.object 尝试了许多不同的迭代,但仍然无济于事。

你的补丁有一些问题。首先,您显然正在使用 from numpy.random import default_rng,因此您必须修补模块中的 default_rng 实例 - 请参阅 where to patch.

其次,integers 是在 default_rng 的实例上调用的,而不是在 class 上调用的,因此您首先必须获取 mock 的实例,通过 return_value.

第三个:它被称为 side_effect,而不是 side_effects(尽管这可能只是您问题中的错字)。

所以一个工作版本可能看起来像这样(稍微调整一下以实际能够测试一些东西):

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