Python unittest 模拟 InfluxDB

huangapple go评论69阅读模式
英文:

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方法,然后在TestCasetearDown方法中调用补丁程序的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()

huangapple
  • 本文由 发表于 2023年6月6日 12:43:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76411498.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定