Python 在模拟中修补发电机
我正在尝试为我的单元测试创建生成器方法的模拟版本。设置返回值很容易:Python 在模拟中修补发电机,python,unit-testing,mocking,Python,Unit Testing,Mocking,我正在尝试为我的单元测试创建生成器方法的模拟版本。设置返回值很容易: patcher = unittest.mock.patch.multiple("__main__.MyClass", method_one=DEFAULT, ... ) patcher.start() MyClass.method_one.return_value = my_mock_gen(some_params) 但是,这只工作一次,每次都必须重置:
patcher = unittest.mock.patch.multiple("__main__.MyClass",
method_one=DEFAULT,
...
)
patcher.start()
MyClass.method_one.return_value = my_mock_gen(some_params)
但是,这只工作一次,每次都必须重置:
for value in my_obj.method_one(some_params):
# do stuff with value
my_obj.method_one.reset_mock() # doesn't work with `yield from` as well
另外,我无法基于
某些参数生成模拟值。有没有一种更好的方法来处理我所缺少的这个场景?解决方案是将生成器
转换为列表
进行测试。它起作用了,但可能不好
#!/usr/bin/python
import mock
import unittest
class FooBar(object):
def method_one(self, a, b):
for i in range(a, b):
yield i * i
def bar(self):
return 'bar'
def mock_generator(a, b):
for i in range(a, b):
yield (i + 1) * i
class TestFooBar(unittest.TestCase):
def test_method_one(self):
# set default to a list
mock_method_one = mock.Mock(return_value=['aaa', 'ccc'])
# this is how I access the class
patcher = mock.patch.multiple(
"python_tools.tests.patch_multiple.FooBar",
method_one=mock_method_one,
bar=mock.Mock(return_value='bar')
)
patcher.start()
# method_one return generator only supposed to be read once
# convert generator to list for testing, crazy?! not sure
# [6, 12] after converting to list
mock_method_one.return_value = list(mock_generator(2, 4))
fb = FooBar()
# no change
self.assertEqual(fb.method_one(200, 500), [6, 12])
# no change
for item in fb.method_one(2, 5):
self.assertTrue(item, [6, 12])
# no change
self.assertEqual(fb.method_one(1, 6), [6, 12])
patcher.stop()
如果您想在调用模拟时运行函数,那就是说,不要返回\u值
:
MyClass.method_one.side_effect = my_mock_gen
关于重置问题,在patcher.start()之前,将method\u one=DEFAULT
,改为method\u one=mock.mock(return\u value='mocked foo!'),
或定义return\u value
?问题是应该在运行中生成一个新的迭代器,而不是通过return\u value=…
重用该迭代器集。我不认为你的建议会改变任何事情,但如果你能提供一个有效的例子,我会接受你的回答。抱歉,但我应该提到,在我的测试中,method\u one
使用了yield
(因为它是一个生成器方法)它不会返回一个简单的列表。副作用
更好,可以更好地控制数据,谢谢!有趣的是,我认为副作用只会产生副作用,而不会影响返回值。