2

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

1 Answer 1

1

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 your Gitlab (gl) object when you want to mock the server response.

For example, to mock out the response when calling 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': '[email protected]',
 'authored_date': '2022-04-01T02:23:14.000+00:00',
 'committer_name': 'Fake Committer',
 'committer_email': '[email protected]',
 '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')

The result of fake_commit will be a ProjectCommit object as if GitLab responded with the fake api data.

>>> fake_commit
<ProjectCommit id:abc123>

You could make the patched function more elaborate to return data based on the URL provided, for example.

Sign up to request clarification or add additional context in comments.

1 Comment

I've had to define a few more variables to make this work. gl = Gitlab(), rm = gitlab.base.RESTManager(gl=gl), and p = gitlab.v4.objects.Project(rm, {}).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.