AttributeError: <module '__main__' from [..] does not have the attribute 'open'
AttributeError: <module '__main__' from [..] does not have the attribute 'open'
我正在为 docker-py 的模块编写测试,但我似乎无法让测试正常工作。
我正在测试的函数如下所示:
def parse_env_file(env_file):
"""
Reads a line-separated environment file.
The format of each line should be "key=value".
"""
environment = []
if os.path.isfile(env_file):
with open(env_file, 'r') as f:
# We can't use f.readlines() here as it's not implemented in Mock
for line in f.read().split('\n'):
parse_line = line.strip().split('=')
if len(parse_line) == 2 and line[0] != '#':
k = parse_line[0]
v = parse_line[1]
environment.append('{0}={1}'.format(k, v))
return environment
然后测试看起来像这样:
def test_parse_env_file_proper(self):
with mock.patch('os.path.isfile', return_value=True):
mock_env_file = 'USER=jdoe\nPASS=secret'
with mock.patch('{}.open'.format(__name__), mock.mock_open(read_data=mock_env_file)):
get_parse_env_file = parse_env_file('foobar')
self.assertEqual(get_parse_env_file, ['USER=jdoe', 'PASS=secret'])
当我 运行 测试时,我得到以下错误:
======================================================================
ERROR: test_parse_env_file_proper (__main__.UtilsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/utils_test.py", line 102, in test_parse_env_file_proper
with mock.patch('{}.open'.format(__name__), mock.mock_open(read_data=mock_env_file)):
File "/Users/mvip/code/private/github/docker-py/.tox/py27/lib/python2.7/site-packages/mock.py", line 1268, in __enter__
original, local = self.get_original()
File "/Users/mvip/code/private/github/docker-py/.tox/py27/lib/python2.7/site-packages/mock.py", line 1242, in get_original
"%s does not have the attribute %r" % (target, name)
AttributeError: <module '__main__' from 'tests/utils_test.py'> does not have the attribute 'open'
此处的任何指示都会有所帮助。
问题是,作为内置函数,open
不是直接在模块中找到的,而是作为 builtins
模块中的后备。
要解决这个问题,您应该在修补时包含 create=True
。
from unittest import mock
with mock.patch(__name__+".open", mock.mock_open(read_data="data"), create=True):
with open("somefile") as f:
assert f.read() == "data"
但是,这只会修补当前模块中的open
(测试中的模块运行,而不是下的模块测试)。
所以你最好这样做:
import unittest
from unittest.mock import mock_open, patch
import module_under_test
def func():
with open("somefile") as f:
return f.read()
class MyTestCase(unittest.TestCase):
def test_open(self):
data = "some data"
with patch.object(module_under_test, "open", mock_open(read_data=data), create=True):
result = module_under_test.func()
self.assertEqual(result, data)
if __name__ == "__main__":
unittest.main()
我正在为 docker-py 的模块编写测试,但我似乎无法让测试正常工作。
我正在测试的函数如下所示:
def parse_env_file(env_file):
"""
Reads a line-separated environment file.
The format of each line should be "key=value".
"""
environment = []
if os.path.isfile(env_file):
with open(env_file, 'r') as f:
# We can't use f.readlines() here as it's not implemented in Mock
for line in f.read().split('\n'):
parse_line = line.strip().split('=')
if len(parse_line) == 2 and line[0] != '#':
k = parse_line[0]
v = parse_line[1]
environment.append('{0}={1}'.format(k, v))
return environment
然后测试看起来像这样:
def test_parse_env_file_proper(self):
with mock.patch('os.path.isfile', return_value=True):
mock_env_file = 'USER=jdoe\nPASS=secret'
with mock.patch('{}.open'.format(__name__), mock.mock_open(read_data=mock_env_file)):
get_parse_env_file = parse_env_file('foobar')
self.assertEqual(get_parse_env_file, ['USER=jdoe', 'PASS=secret'])
当我 运行 测试时,我得到以下错误:
======================================================================
ERROR: test_parse_env_file_proper (__main__.UtilsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/utils_test.py", line 102, in test_parse_env_file_proper
with mock.patch('{}.open'.format(__name__), mock.mock_open(read_data=mock_env_file)):
File "/Users/mvip/code/private/github/docker-py/.tox/py27/lib/python2.7/site-packages/mock.py", line 1268, in __enter__
original, local = self.get_original()
File "/Users/mvip/code/private/github/docker-py/.tox/py27/lib/python2.7/site-packages/mock.py", line 1242, in get_original
"%s does not have the attribute %r" % (target, name)
AttributeError: <module '__main__' from 'tests/utils_test.py'> does not have the attribute 'open'
此处的任何指示都会有所帮助。
问题是,作为内置函数,open
不是直接在模块中找到的,而是作为 builtins
模块中的后备。
要解决这个问题,您应该在修补时包含 create=True
。
from unittest import mock
with mock.patch(__name__+".open", mock.mock_open(read_data="data"), create=True):
with open("somefile") as f:
assert f.read() == "data"
但是,这只会修补当前模块中的open
(测试中的模块运行,而不是下的模块测试)。
所以你最好这样做:
import unittest
from unittest.mock import mock_open, patch
import module_under_test
def func():
with open("somefile") as f:
return f.read()
class MyTestCase(unittest.TestCase):
def test_open(self):
data = "some data"
with patch.object(module_under_test, "open", mock_open(read_data=data), create=True):
result = module_under_test.func()
self.assertEqual(result, data)
if __name__ == "__main__":
unittest.main()