我的环境包含版本为1.9.0
的Python 3.7.5和influx-client库。我想模拟select_where
对象的InfluxDB
方法,但是在我的代码(如下所示)中,它导致AttributeError
出现,例如
AttributeError: <class 'influx.InfluxDB'> does not have the attribute 'select_where'
和
AttributeError: 'InfluxDB' object attribute 'select_where' is read-only
influx_mock
├── db_connection
│ ├── __init__.py
│ └── __main__.py
└── tests
└── test_db_connection.py
文件内容:
# db_connection/__main__.py
from influx import InfluxDB
def get_data(influx_url):
client = InfluxDB(influx_url)
return client.select_where(
'database',
'measurement',
fields='foo',
where='bar > 0'
)
if __name__ == "__main__":
influx_url = 'http://127.0.0.1:8086'
data = get_data(influx_url)
# ...process data
# db_connection/__init__.py
from .__main__ import get_data
# tests/test_db_connection
import unittest
from unittest.mock import patch
from influx import InfluxDB
from db_connection import get_data
class DbConnection(unittest.TestCase):
def setUp(self):
self.influx_url = 'http://127.0.0.1:8086'
self.mock_data = { 'mock data' }
def test_patching_InfluxDB(self):
with patch.object(InfluxDB, 'select_where', return_value=self.mock_data):
data = get_data(self.influx_url)
self.assertEqual(self.mock_data, data)
def test_patching_client(self):
client = InfluxDB(self.influx_url)
with patch.object(client, 'select_where', return_value=self.mock_data):
data = get_data(self.influx_url)
self.assertEqual(self.mock_data, data)
使用python -m unittest discover -s tests/
运行单元测试会导致
EE
======================================================================
ERROR: test_patching_InfluxDB (test_db_connection.DbConnection)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<redacted>/influx_mock/tests/test_db_connection.py", line 17, in test_patching_InfluxDB
with patch.object(InfluxDB, 'select_where', return_value=self.mock_data):
File "<redacted>/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/mock.py", line 1319, in __enter__
original, local = self.get_original()
File "<redacted>/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/mock.py", line 1293, in get_original
"%s does not have the attribute %r" % (target, name)
AttributeError: <class 'influx.InfluxDB'> does not have the attribute 'select_where'
======================================================================
ERROR: test_patching_client (test_db_connection.DbConnection)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<redacted>/influx_mock/tests/test_db_connection.py", line 24, in test_patching_client
with patch.object(client, 'select_where', return_value=self.mock_data):
File "<redacted>/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/mock.py", line 1410, in __enter__
setattr(self.target, self.attribute, new_attr)
AttributeError: 'InfluxDB' object attribute 'select_where' is read-only
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (errors=2)
直接修补对象InfluxDB
(test_patching_InfluxDB
)引发AttributeError
,抱怨它不具有属性select_where
。但是,looking at the source code表示InfluxDB
确实具有称为select_where
的类方法。令人困惑的是,该类用@pytool.lang.hashed_singleton
装饰,请参见文档中的摘录:
包装一个类以创建它的哈希单例版本。散列的单例就像单例,因为每个呼叫签名只有一个类的实例。
单例保持为弱引用,因此,如果您的程序停止引用散列的单例,则如果Python解释器已垃圾回收原始实例,则可能会得到一个新实例。
-https://pytool.readthedocs.io/en/latest/pytool.html#pytool.lang.hashed_singleton
在碰上这个问题之后,我尝试了第二种修补对象(test_patching_client
)的方法,认为如果我创建了一个InfluxDB
实例,并且该实例在测试中与源代码中的参数相同,则该实例将是相同的对象使我可以在测试中模拟该方法,从而在两个地方都将其覆盖。但这导致了只读属性错误,所以现在我没有主意了。