python-gitlab 模拟 ProjectCommit 对象 API V4
python-gitlab mocking ProjectCommit objects API V4
我正在尝试创建一个 gitlab.v4.objects.ProjectCommit
的模拟对象,以便在我使用 python-gitlab
api 开发的工具之间执行集成测试。为了通过使用 ProjectCommit
定义模拟 RESTManager
对象来创建 ProjectCommit
模拟对象:
gitlab.v4.objects.ProjectCommit(
manager: gitlab.base.RESTManager,
attrs: Dict[str, Any], *, created_from_list: bool = False)
- 因此我尝试了以下方法
from unittest.mock import Mock
from gitlab.base import RESTManager, RESTObject
from gitlab.client import Gitlab
session_mock = Mock(spec=Gitlab)
rest_object_mock = Mock(spec=RESTObject)
rest_manager_mock = Mock(spec=RESTManager,
gl=session_mock,
parent=rest_object_mock)
rest_manager_mock.gitlab = session_mock
# ProjectCommit mock object
# commit_recipe is just fake commit data
project_commit = ProjectCommit(manager=rest_manager_mock, attrs=commit_recipe)
- 输出
File "gitlab_mocks.py", line 24, in <module>
ProjectCommit(manager=rest_manager_mock,
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 88, in __init__
self._create_managers()
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 207, in _create_managers
manager = cls(self.manager.gitlab, parent=self)
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 356, in __init__
self._computed_path = self._compute_path()
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 371, in _compute_path
data = {
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 372, in <dictcomp>
self_attr: getattr(self._parent, parent_attr, None)
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 126, in __getattr__
return self.__dict__["_parent_attrs"][name]
TypeError: 'Mock' object is not subscriptable
查看 RestObject
实施,ProjectCommit
初始化失败 here,
我该如何克服这个问题?是否有创建 ProjectCommit
模拟对象的替代方法?
您可以找到 ProjectCommit 文档 here
你真正需要模拟的是外部系统(例如 gitlab returning 一个特定的响应)。模拟 HTTP 响应比模拟库内部更容易。这可能也比模拟库的核心组件更有意义——否则你只是在测试你的代码和模拟之间的“集成”,这有点没用。
一种方法是在您想要模拟服务器响应时有选择地修补 Gitlab
(gl
) 对象的 http_
方法。
例如,模拟调用project.commits.get
时的响应:
from unittest import mock
# ...
# false commit response data
# https://docs.gitlab.com/ee/api/commits.html#get-a-single-commit
fake_data = {'id': 'abc123',
'short_id': 'abc',
'created_at': '2022-04-01T02:23:14.000+00:00',
'parent_ids': ['a', 'b'],
'title': "A fake title",
'message': 'A fake message',
'author_name': 'Fake Author',
'author_email': 'fake.author@example.com',
'authored_date': '2022-04-01T02:23:14.000+00:00',
'committer_name': 'Fake Committer',
'committer_email': 'fake.committer@example.com',
'committed_date': '2022-04-01T02:23:14.000+00:00',
'trailers': {},
'web_url': 'https://gitlab.example.com/fake/project/-/commit/abc123',
'project_id': 1234}
def fake_response(*args, **kwargs):
"""Used to replace Gitlab.http_get (or other) method(s)"""
return fake_data
with mock.patch.object(gl, 'http_get', new=fake_response):
fake_commit = p.commits.get(id='abc123')
fake_commit
的结果将是一个 ProjectCommit
对象,就好像 GitLab 用假 api 数据响应一样。
>>> fake_commit
<ProjectCommit id:abc123>
例如,您可以根据提供的 URL 使修补函数更详细地处理 return 数据。
我正在尝试创建一个 gitlab.v4.objects.ProjectCommit
的模拟对象,以便在我使用 python-gitlab
api 开发的工具之间执行集成测试。为了通过使用 ProjectCommit
定义模拟 RESTManager
对象来创建 ProjectCommit
模拟对象:
gitlab.v4.objects.ProjectCommit(
manager: gitlab.base.RESTManager,
attrs: Dict[str, Any], *, created_from_list: bool = False)
- 因此我尝试了以下方法
from unittest.mock import Mock
from gitlab.base import RESTManager, RESTObject
from gitlab.client import Gitlab
session_mock = Mock(spec=Gitlab)
rest_object_mock = Mock(spec=RESTObject)
rest_manager_mock = Mock(spec=RESTManager,
gl=session_mock,
parent=rest_object_mock)
rest_manager_mock.gitlab = session_mock
# ProjectCommit mock object
# commit_recipe is just fake commit data
project_commit = ProjectCommit(manager=rest_manager_mock, attrs=commit_recipe)
- 输出
File "gitlab_mocks.py", line 24, in <module>
ProjectCommit(manager=rest_manager_mock,
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 88, in __init__
self._create_managers()
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 207, in _create_managers
manager = cls(self.manager.gitlab, parent=self)
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 356, in __init__
self._computed_path = self._compute_path()
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 371, in _compute_path
data = {
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 372, in <dictcomp>
self_attr: getattr(self._parent, parent_attr, None)
File "env_auto/lib/python3.8/site-packages/gitlab/base.py", line 126, in __getattr__
return self.__dict__["_parent_attrs"][name]
TypeError: 'Mock' object is not subscriptable
查看 RestObject
实施,ProjectCommit
初始化失败 here,
我该如何克服这个问题?是否有创建 ProjectCommit
模拟对象的替代方法?
您可以找到 ProjectCommit 文档 here
你真正需要模拟的是外部系统(例如 gitlab returning 一个特定的响应)。模拟 HTTP 响应比模拟库内部更容易。这可能也比模拟库的核心组件更有意义——否则你只是在测试你的代码和模拟之间的“集成”,这有点没用。
一种方法是在您想要模拟服务器响应时有选择地修补 Gitlab
(gl
) 对象的 http_
方法。
例如,模拟调用project.commits.get
时的响应:
from unittest import mock
# ...
# false commit response data
# https://docs.gitlab.com/ee/api/commits.html#get-a-single-commit
fake_data = {'id': 'abc123',
'short_id': 'abc',
'created_at': '2022-04-01T02:23:14.000+00:00',
'parent_ids': ['a', 'b'],
'title': "A fake title",
'message': 'A fake message',
'author_name': 'Fake Author',
'author_email': 'fake.author@example.com',
'authored_date': '2022-04-01T02:23:14.000+00:00',
'committer_name': 'Fake Committer',
'committer_email': 'fake.committer@example.com',
'committed_date': '2022-04-01T02:23:14.000+00:00',
'trailers': {},
'web_url': 'https://gitlab.example.com/fake/project/-/commit/abc123',
'project_id': 1234}
def fake_response(*args, **kwargs):
"""Used to replace Gitlab.http_get (or other) method(s)"""
return fake_data
with mock.patch.object(gl, 'http_get', new=fake_response):
fake_commit = p.commits.get(id='abc123')
fake_commit
的结果将是一个 ProjectCommit
对象,就好像 GitLab 用假 api 数据响应一样。
>>> fake_commit
<ProjectCommit id:abc123>
例如,您可以根据提供的 URL 使修补函数更详细地处理 return 数据。