pytest - 通过 configparser.ConfigParser() / config.read() 模拟配置 [<section_name>]
pytest - mock config[<section_name>] via configparser.ConfigParser() / config.read()
目标:我想测试我们的网络服务连接包装器,例如GitLab,SFTP,MySQL。
我卡在了下面的部分:
config = configparser.ConfigParser()
config.read(r"C:\git\config.ini")
如何 mock/patch/MagicMock 以便 config[<section_name>]
返回给定键在 test_gitlab.py 中定义的值。由于我们在各种 .py 文件中对上述结构进行了各种调用,因此如果可能的话,我希望不要更改实际的 config.read(r"C:\git\config.ini")
调用。
看似有希望但失败的方法:
- mock
configparser.ConfigParser.read.return_value = config_dict
--> 这不会改变变量配置,而是 returns 没有保存(最佳情况)或破坏 运行[= 的字典38=]
- 通过
config.add_section('GITLAB_TEST'), config.set('GITLAB_TEST', 'tokken', 'test_token')
在 test_pytest.py 中添加 'GITLAB_TEST' 部分 --> 配置及其定义的部分在 gitlab.py 中被覆盖为 config = configparser.ConfigParser()
# ./module/io/gitlab.py
import configparser
import os
import sys
import gitlab
class GitlabApi:
def __init__(self, client=None):
if sys.platform == "win32":
config = configparser.ConfigParser()
config.read(r"C:\git\config.ini")
self.token = config["GITLAB_{}".format(client)]["token"]
def return_client(self):
self.api = gitlab.Gitlab(
"https://gitlab.company_name.com",
private_token=self.token
)
self.api.auth()
return self.api
# ./tests/test_gitlab.py
import pytest
from unittest.mock import MagicMock
from unittest.mock import Mock
from ane.io import gitlab
def test_return_client_win32():
gitlab.sys = Mock(platform="win32")
gitlab.gitlab.Gitlab = MagicMock()
test_client, expected_private_token, expected_url = "test", "test_token", "test_url"
config_dict = {
"GITLAB_TEST": {"token": "test_token"},
"GITLAB_SCRIPTS": {"token": "script_token"},
}
# following does not work
gitlab.configparser.ConfigParser = MagicMock()
gitlab.configparser.ConfigParser.return_value.read.return_value = config_dict
gitlab.GitlabApi(client=test_client) # mocked object
gitlab.gitlab.Gitlab.assert_called_once_with(
expected_url, private_token=expected_private_token
)
一些 Whosebugs 没有为我解决问题,但可能对其他人有帮助:
python 3.7
我对上述问题的解决方案:模拟 config.read() 调用的内置 open()。 returned fake_config_file
基本上是一个以字节为单位的文件。
def test_return_client_win32():
gitlab.sys = Mock(platform="win32")
gitlab.gitlab.Gitlab = MagicMock()
test_client = 'client'
expected_private_token = 'expected_private_token'
expected_url = "https://gitlab.company.name"
fake_config_file = TextIOWrapper(
BytesIO(
b"[GITLAB_TEST]\ntoken: test_token\n"
b"[GITLAB_SCRIPTS]\ntoken: script_token"
)
)
gitlab.configparser.open = MagicMock(return_value=fake_config_file)
gitlab.GitlabApi(client=test_client)
gitlab.gitlab.Gitlab.assert_called_once_with(
expected_url, private_token=expected_private_token
)
总的来说,我目前建议的做法是:寻找字符串类型return。深入研究方法,直到找到 return 字符串或类似方法。这就是你嘲笑的。
目标:我想测试我们的网络服务连接包装器,例如GitLab,SFTP,MySQL。 我卡在了下面的部分:
config = configparser.ConfigParser()
config.read(r"C:\git\config.ini")
如何 mock/patch/MagicMock 以便 config[<section_name>]
返回给定键在 test_gitlab.py 中定义的值。由于我们在各种 .py 文件中对上述结构进行了各种调用,因此如果可能的话,我希望不要更改实际的 config.read(r"C:\git\config.ini")
调用。
看似有希望但失败的方法:
- mock
configparser.ConfigParser.read.return_value = config_dict
--> 这不会改变变量配置,而是 returns 没有保存(最佳情况)或破坏 运行[= 的字典38=] - 通过
config.add_section('GITLAB_TEST'), config.set('GITLAB_TEST', 'tokken', 'test_token')
在 test_pytest.py 中添加 'GITLAB_TEST' 部分 --> 配置及其定义的部分在 gitlab.py 中被覆盖为config = configparser.ConfigParser()
# ./module/io/gitlab.py
import configparser
import os
import sys
import gitlab
class GitlabApi:
def __init__(self, client=None):
if sys.platform == "win32":
config = configparser.ConfigParser()
config.read(r"C:\git\config.ini")
self.token = config["GITLAB_{}".format(client)]["token"]
def return_client(self):
self.api = gitlab.Gitlab(
"https://gitlab.company_name.com",
private_token=self.token
)
self.api.auth()
return self.api
# ./tests/test_gitlab.py
import pytest
from unittest.mock import MagicMock
from unittest.mock import Mock
from ane.io import gitlab
def test_return_client_win32():
gitlab.sys = Mock(platform="win32")
gitlab.gitlab.Gitlab = MagicMock()
test_client, expected_private_token, expected_url = "test", "test_token", "test_url"
config_dict = {
"GITLAB_TEST": {"token": "test_token"},
"GITLAB_SCRIPTS": {"token": "script_token"},
}
# following does not work
gitlab.configparser.ConfigParser = MagicMock()
gitlab.configparser.ConfigParser.return_value.read.return_value = config_dict
gitlab.GitlabApi(client=test_client) # mocked object
gitlab.gitlab.Gitlab.assert_called_once_with(
expected_url, private_token=expected_private_token
)
一些 Whosebugs 没有为我解决问题,但可能对其他人有帮助:
python 3.7
我对上述问题的解决方案:模拟 config.read() 调用的内置 open()。 returned fake_config_file
基本上是一个以字节为单位的文件。
def test_return_client_win32():
gitlab.sys = Mock(platform="win32")
gitlab.gitlab.Gitlab = MagicMock()
test_client = 'client'
expected_private_token = 'expected_private_token'
expected_url = "https://gitlab.company.name"
fake_config_file = TextIOWrapper(
BytesIO(
b"[GITLAB_TEST]\ntoken: test_token\n"
b"[GITLAB_SCRIPTS]\ntoken: script_token"
)
)
gitlab.configparser.open = MagicMock(return_value=fake_config_file)
gitlab.GitlabApi(client=test_client)
gitlab.gitlab.Gitlab.assert_called_once_with(
expected_url, private_token=expected_private_token
)
总的来说,我目前建议的做法是:寻找字符串类型return。深入研究方法,直到找到 return 字符串或类似方法。这就是你嘲笑的。