I am trying to create a mock object of gitlab.v4.objects.ProjectCommit to perform integration tests between a tool I am developing with python-gitlab api. In order to create a ProjectCommit mock object by mocking the RESTManager object using ProjectCommit definition:
gitlab.v4.objects.ProjectCommit(
manager: gitlab.base.RESTManager,
attrs: Dict[str, Any], *, created_from_list: bool = False)
- Therefore I tried the following
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)
- Output
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
Looking at RestObject implementation, ProjectCommit initialisation is failing here,
How can I overcome this problem ? Is there an alternative way to create ProjectCommit mock object?
You can find ProjectCommit documentation here
The real thing you need to mock is the outside system (e.g. gitlab returning a particular response). It's easier to mock the HTTP response instead of the library internals. This probably also makes more sense than mocking out core components of the library -- otherwise you'd just be testing the "integration" between your code and mocks, which is somewhat useless.
One way would be to selectively patch the
http_methods of yourGitlab(gl) object when you want to mock the server response.For example, to mock out the response when calling
project.commits.get:The result of
fake_commitwill be aProjectCommitobject as if GitLab responded with the fake api data.You could make the patched function more elaborate to return data based on the URL provided, for example.