在python中模拟文件对象或可迭代对象 [英] Mocking file objects or iterables in python
问题描述
哪种方法适合模拟和测试由 open()返回的iters对象的代码,使用 mock 库?
Which way is proper for mocking and testing code that iters object returned by open(), using mock library?
whitelist_data.py
:
WHITELIST_FILE = "testdata.txt"
format_str = lambda s: s.rstrip().lstrip('www.')
whitelist = None
with open(WHITELIST_FILE) as whitelist_data:
whitelist = set(format_str(line) for line in whitelist_data)
if not whitelist:
raise RuntimeError("Can't read data from %s file" % WHITELIST_FILE)
def is_whitelisted(substr):
return 1 if format_str(substr) in whitelist else 0
这是我尝试进行测试的方式.
Here's how I try to test it.
import unittest
import mock
TEST_DATA = """
domain1.com
domain2.com
domain3.com
"""
class TestCheckerFunctions(unittest.TestCase):
def test_is_whitelisted_method(self):
open_mock = mock.MagicMock()
with mock.patch('__builtin__.open',open_mock):
manager = open_mock.return_value.__enter__.return_value
manager.__iter__ = lambda s: iter(TEST_DATA.splitlines())
from whitelist_data import is_whitelisted
self.assertTrue(is_whitelisted('domain1.com'))
if __name__ == '__main__':
unittest.main()
python tests.py
的结果是:
$ python tests.py
E
======================================================================
ERROR: test_is_whitelisted_method (__main__.TestCheckerFunctions)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests.py", line 39, in test_is_whitelisted_method
from whitelist_data import is_whitelisted
File "/Users/supa/Devel/python/whitelist/whitelist_data.py", line 20, in <module>
whitelist = set(format_str(line) for line in whitelist_data)
TypeError: 'Mock' object is not iterable
----------------------------------------------------------------------
Ran 1 test in 0.001s
UPD::由于Adam,我重新安装了模拟库(pip install -e hg+https://code.google.com/p/mock#egg=mock
)并更新了tests.py.就像魅力一样.
UPD: Thanks to Adam, I've reinstalled mock library(pip install -e hg+https://code.google.com/p/mock#egg=mock
) and updated tests.py. Works like a charm.
推荐答案
您正在寻找MagicMock
.这支持迭代.
You're looking for a MagicMock
. This supports iteration.
在模拟0.80beta4中,patch
返回MagicMock
.因此,这个简单的示例有效:
In mock 0.80beta4, patch
returns a MagicMock
. So this simple example works:
import mock
def foo():
for line in open('myfile'):
print line
@mock.patch('__builtin__.open')
def test_foo(open_mock):
foo()
assert open_mock.called
如果您正在运行模拟0.7.x(看起来像您一样),我认为您不能仅使用补丁来完成此任务.您需要分别创建模拟,然后将其传递到补丁中:
If you're running mock 0.7.x (It looks like you are), I don't think you can accomplish this with patch alone. You'll need to create the mock separately, then pass it into patch:
import mock
def foo():
for line in open('myfile'):
print line
def test_foo():
open_mock = mock.MagicMock()
with mock.patch('__builtin__.open', open_mock):
foo()
assert open_mock.called
注意-我已经使用py.test运行了这些,但是,这些相同的方法也可以用于unittest.
Note - I've run these with py.test, however, these same approaches will work with unittest as well.
这篇关于在python中模拟文件对象或可迭代对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!