python-3.xunit-testinggitpython

Mocking GitPython Repo Calls


I've got a class with a function that adds unstaged changes in a git repo and commits them

    def commit_local_changes(self, repo_path):
        repo = Repo(repo_path)
        changed_files = repo.git.diff(None, name_only=True).splitlines()
        if changed_files:
            for file in changed_files:
                repo.git.add(file)
            repo.git.commit("-m", "some commit message")
        return repo.head.object.hexsha

I'm trying to write unit tests to go over this functionality and I was to have repo.git.diff(None, name_only=True) actually return something besides a mock. I've tried to set up the tests like so:

    
@patch("myModule.Repo")
def test_commit_local_changes(self, mock_repo):
       mock_repo.return_value
            .git.return_value
            .diff.return_value = 'file1\nfile2'

but when I print changed_files in the main method and call the mock I see that it's just some MagicMock:

<MagicMock name='Repo().git.diff().splitlines()' id='140551053340304'>

Solution

  • My issue was a lack of understanding of Python's attribute mocking versus return value for a function result.

    In my case, Repo() is a function creating an instance of the class Repo (python may have different names for these, I'm more familiar with Java). So I needed to mock the return value of Repo(), then Python will mock it's attributes for me, then I needed to mock the return value of the call to diff(). The following worked:

     mock_repo.return_value.git.diff.return_value = "file1\nfile2"