Search code examples
pythonmockingpython-unittestpython-gitlab

Trouble mocking the return value of python-gitlab method


I am trying to mock the return value of the following method

import gitlab
from unittest.mock import patch

def get_all_iters():
   gl = gitlab.Gitlab(url='test_url', private_token)
   result = gl.groups.get(1).iterations.list() # trying to mock the result of this method call

   return result

@patch('gitlab.Gitlab')
@patch('gitlab.v4.objects.GroupManager')
@patch('gitlab.mixins.ListMixin.list')
def test_my_code(mockGitlab, mockGroup, mockList):
   mockList.return_value = ['a', 'b']
   result = get_all_iters()
   print(result)

Although I have tried to mock the return value of the method call, it is still returning the mock object instead of what I tried to mock

<MagicMock name='Gitlab().groups.get().iterations.list()' id='1688988996464'>

Solution

  • I have found the following solution for your problem (I have tested it in my system):

    import gitlab
    from unittest.mock import patch
    
    def get_all_iters():
       #gl = gitlab.Gitlab(url='test_url', private_token) # <--- Remove your instruction and substitute with the following
       gl = gitlab.Gitlab(url='test_url', private_token='test_token_value')  # <--- HERE I have set the value for the argument private_token
       result = gl.groups.get(1).iterations.list() # trying to mock the result of this method call
       return result
    
    # I leave only one patch() as decorator, while other mocks are managed 
    # by context managers inserted into the body of the test method
    @patch('gitlab.Gitlab')
    def test_my_code(mockGitlab):
        instance_gl = mockGitlab.return_value
        with patch.object(instance_gl, 'groups') as mock_groups:
            with patch.object(mock_groups, 'get') as mock_get:
                instance_get = mock_get.return_value
                with patch.object(instance_get, 'iterations') as mock_iterations:
                    with patch.object(mock_iterations, 'list') as mockList:
                        # -------> FINALLY here are your test instructions
                        mockList.return_value = ['a', 'b']
                        result = get_all_iters()
                        print(result)
    
    test_my_code()
    

    The execution of the test method on my system is:

    ['a', 'b']
    

    that is the print of the desired value for result set by your instruction mockList.return_value = ['a', 'b'].

    Why are there so many mocks object?

    Note the instructions:

    instance_gl = mockGitlab.return_value
    instance_get = mock_get.return_value
    

    By those instructions we can get the right Mock objects.

    Furthermore note the presence of the instructions patch.object() and not only of the patch() instruction.

    There is probably a simpler solution, but since you desire to mock the list get by the complex instruction:

    gl.groups.get(1).iterations.list()
    

    I have been able to find only this way!


    This post is old but useful to add more details to my explanation.