英文:
Python unittest mocking influxdb
问题
这是要翻译的代码部分:
I want to test a class which passes data to an influx-database.
For that purpose I use influxdb.InfluxDBClient. For the unit-tests I want to mock influxdb.InfluxDBClient, but it seems that this is not working. I always get timeouts, so the mocking does not work at all.
This is the class I want to test:
```python
''' Client for influxDB1. '''
from influxdb import InfluxDBClient
class Influx1Writer:
''' Client to access influxDB1. '''
def __init__(self, host, port, user, password, dbname, usessl) -> None:
''' Initializer, will be called from constructor. '''
self.client = InfluxDBClient(
host=host,
port=port,
username=user,
password=password,
database=dbname,
ssl=usessl)
self.client.create_database(dbname)
self.client.switch_database(dbname)
self.client.switch_user(user, password)
This is the test case
''' Unittest writer for influxdb, version 1. '''
import unittest
from unittest.mock import patch, MagicMock
from influxdb import InfluxDBClient
from influx.influx_writer_1 import Influx1Writer
class TestInflux1Writer(unittest.TestCase):
''' Unittests of Influx1Writer. '''
host = "host"
port = 8080
user = "user"
password = "password"
dbname = "dbname"
usessl = False
def setUp(self) -> None:
''' Setup test fixture. '''
mock_influx = MagicMock('influxdb.InfluxDBClient')
self.handler = Influx1Writer(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
mock_influx.assert_called_with(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
super().setUp()
def tearDown(self) -> None:
''' Tear down test fixture. '''
self.handler = None
super().tearDown()
###
@patch('influxdb.InfluxDBClient')
@patch('influxdb.InfluxDBClient.create_database')
@patch('influxdb.InfluxDBClient.switch_database')
@patch('influxdb.InfluxDBClient.switch_user')
def test_01a_init_called(self, mock_client, mock_create_database, mock_switch_database, mock_switch_user) -> None:
''' Check InfluxDBClient is called with parameters. '''
mock_client.__init__.assert_called_with(self.host, self.port, self.user, self.password, self.dbname, self.usessl)
mock_create_database.assert_called_with(self.dbname)
mock_switch_database.assert_called_with(self.dbname)
mock_switch_user.assert_called_with(self.dbname)
self.assertEqual(type(self.handler), Influx1Writer)
When the test is executed, a timeout will occur. This means that influxdb.InfluxDBClient is not mocked.
What am I doing wrong here?
Found the solution, thank you @blhsing
def setUp(self) -> None:
''' Setup test fixture. '''
self.patch_client = patch('influx.influx_writer_1.InfluxDBClient')
mock_influx = self.patch_client.start()
self.client = Influx1Writer(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
mock_influx.assert_called_with( host=self.host, \
port=self.port, \
username=self.user, \
password=self.password, \
database=self.dbname, \
ssl=self.usessl)
super().setUp()
英文:
I want to test a class which passes data to an influx-database.
For that purpose I use influxdb.InfluxDBClient. For the unit-tests I want to mock influxdb.InfluxDBClient, but it seems that this is not working. I always get timeouts, so the mocking does not work at all.
This is the class I want to test:
''' Client for influxDB1. '''
from influxdb import InfluxDBClient
class Influx1Writer:
''' Client to access influxDB1. '''
def __init__(self, host, port, user, password, dbname, usessl) -> None:
''' Initializer, will be called from constructor. '''
self.client = InfluxDBClient(
host=host,
port=port,
username=user,
password=password,
database=dbname,
ssl=usessl)
self.client.create_database(dbname)
self.client.switch_database(dbname)
self.client.switch_user(user, password)
This is the test case
''' Unittest writer for influxdb, version 1. '''
import unittest
from unittest.mock import patch, MagicMock
from influxdb import InfluxDBClient
from influx.influx_writer_1 import Influx1Writer
class TestInflux1Writer(unittest.TestCase):
''' Unittests of Influx1Writer. '''
host = "host"
port = 8080
user = "user"
password = "password"
dbname = "dbname"
usessl = False
def setUp(self) -> None:
''' Setup test fixture. '''
mock_influx = MagicMock('influxdb.InfluxDBClient')
self.handler = Influx1Writer(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
mock_influx.assert_called_with(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
super().setUp()
def tearDown(self) -> None:
''' Tear down test fixture. '''
self.handler = None
super().tearDown()
###
@patch('influxdb.InfluxDBClient')
@patch('influxdb.InfluxDBClient.create_database')
@patch('influxdb.InfluxDBClient.switch_database')
@patch('influxdb.InfluxDBClient.switch_user')
def test_01a_init_called(self, mock_client, mock_create_database, mock_switch_database, mock_switch_user) -> None:
''' Check InfluxDBClient is called with parameters. '''
mock_client.__init__.assert_called_with(self.host, self.port, self.user, self.password, self.dbname, self.usessl)
mock_create_database.assert_called_with(self.dbname)
mock_switch_database.assert_called_with(self.dbname)
mock_switch_user.assert_called_with(self.dbname)
self.assertEqual(type(self.handler), Influx1Writer)
When the test is executed, a timeout will occur. This means that influxdb.InfluxDBClient is not mocked.
What am I doing wrong here?
Found the solution, thank you @blhsing
def setUp(self) -> None:
''' Setup test fixture. '''
self.patch_client = patch('influx.influx_writer_1.InfluxDBClient')
mock_influx = self.patch_client.start()
self.client = Influx1Writer(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
mock_influx.assert_called_with( host=self.host, \
port=self.port, \
username=self.user, \
password=self.password, \
database=self.dbname, \
ssl=self.usessl)
super().setUp()
答案1
得分: 1
以下是您要翻译的内容:
"在您补丁influxdb.InfluxDBClient
之时,它已被导入到模块influx.influx_writer_1
的命名空间中,因此该模块保留对原始InfluxDBClient
的引用,即使在补丁influxdb.InfluxDBClient
之后,仍然有效。相反,您应该补丁influx.influx_writer_1.InfluxDBClient
,以便在模块influxdb.InfluxDBClient
内可以重新分配名称InfluxDBClient
。
此外,您应该使用patch
而不是MagicMock
来补丁对象。要在TestCase
的测试中为对象打补丁,请在setUp
方法中调用补丁程序的start
方法,然后在TestCase
的tearDown
方法中调用补丁程序的stop
方法来恢复原始对象:
def setUp(self) -> None:
''' 设置测试夹具。 '''
self.patcher = patch('influx.influx_writer_1.InfluxDBClient')
self.patcher.start()
self.handler = Influx1Writer(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
Influx1Writer.assert_called_with(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
super().setUp()
def tearDown(self) -> None:
''' 拆卸测试夹具。 '''
self.patcher.stop()
self.handler = None
super().tearDown()
请注意,此处仅返回翻译后的内容,不包括其他内容。
英文:
By the time you patch influxdb.InfluxDBClient
, it is already imported into the namespace of the module influx.influx_writer_1
so the module keeps a reference to the original InfluxDBClient
even after influxdb.InfluxDBClient
is patched. Instead, you should patch influx.influx_writer_1.InfluxDBClient
so the name InfluxDBClient
within the module influxdb.InfluxDBClient
can actually be reassigned.
Also, you should use patch
instead of MagicMock
to patch an object. To patch an object for the tests in a TestCase
, call the start
method of the patcher in the setUp
method, and then restore the original object by calling the stop
method of the patcher in the tearDown
method of the TestCase
:
def setUp(self) -> None:
''' Setup test fixture. '''
self.patcher = patch('influx.influx_writer_1.InfluxDBClient')
self.patcher.start()
self.handler = Influx1Writer(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
Influx1Writer.assert_called_with(self.host, \
self.port, \
self.user, \
self.password, \
self.dbname, \
self.usessl)
super().setUp()
def tearDown(self) -> None:
''' Tear down test fixture. '''
self.patcher.stop()
self.handler = None
super().tearDown()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论