如何在 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
我正在为一个函数编写单元测试,在实际函数中我有:
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