【问题标题】:pytest - mock config[<section_name>] via configparser.ConfigParser() / config.read()pytest - 通过 configparser.ConfigParser() / config.read() 模拟配置 [<section_name>]
【发布时间】:2021-06-26 10:07:26
【问题描述】:

目标:我想测试我们的网络服务连接包装器,例如GitLab、SFTP、MySQL。 我被困在以下部分:

config = configparser.ConfigParser()
config.read(r"C:\git\config.ini")

我如何模拟/补丁/MagicMock 以便config[&lt;section_name&gt;] 返回一个在 test_gitlab.py 中为给定键定义的值。由于我们在各种 .py 文件中对上述结构进行了各种调用,如果可能的话,我希望不要更改实际的 config.read(r"C:\git\config.ini") 调用。

看似有希望但失败的方法:

  • mock configparser.ConfigParser.read.return_value = config_dict --> 这不会改变变量配置,而是返回(最佳情况)未保存或中断运行的 dict
  • 通过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
        )

一些没有为我解决问题但可能对其他人有所帮助的stackoverflows:

python 3.7

【问题讨论】:

    标签: python mocking connection pytest


    【解决方案1】:

    我对上述问题的解决方案:模拟 config.read() 调用的内置 open()。返回的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
        )
    

    总的来说,我目前建议的方法是:寻找字符串类型的返回值。深入研究方法,直到找到返回字符串或类似的方法。这就是你嘲笑的。

    【讨论】:

      猜你喜欢
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-14
      相关资源
      最近更新 更多