admin管理员组

文章数量:1388912

I have a scenario where I create a git.repo.base.Repo object in a "someFile.py":

def someFunction():
    //some part of code
    repo = Repo(path)
    repo.head.reference = repomit(someHash)
    repo.head.reset(index=True, working_tree=True)
    //some part of code

How do I mock the Repo(path) call and rest of the part of the code while writing tests?

I tried @patch('git.repo.base.Repo') with mockRepo = MagicMock.return_value and a couple more scenarios but I always get error:

git.exc.NoSuchPathError: somePath/path

What should be the approach here?

Also, when we have multiple mocks on the same method, for example:

@mock.patch.object('1')
@mock.patch.object('2')
@mock.patch.object('3')
def test_something(mocker1, mocker2, mocker3)

How mocker1, mocker2, mocker3 are mapped?

I have a scenario where I create a git.repo.base.Repo object in a "someFile.py":

def someFunction():
    //some part of code
    repo = Repo(path)
    repo.head.reference = repomit(someHash)
    repo.head.reset(index=True, working_tree=True)
    //some part of code

How do I mock the Repo(path) call and rest of the part of the code while writing tests?

I tried @patch('git.repo.base.Repo') with mockRepo = MagicMock.return_value and a couple more scenarios but I always get error:

git.exc.NoSuchPathError: somePath/path

What should be the approach here?

Also, when we have multiple mocks on the same method, for example:

@mock.patch.object('1')
@mock.patch.object('2')
@mock.patch.object('3')
def test_something(mocker1, mocker2, mocker3)

How mocker1, mocker2, mocker3 are mapped?

Share Improve this question edited Mar 24 at 21:18 Shiva Shukla asked Mar 15 at 0:09 Shiva ShuklaShiva Shukla 237 bronze badges 3
  • It's hard to understand what do you want to achieve. Code of someFunction is not correct Python. If someFunction works only with Repo object, what do you aim to test if you mock the Repo object? BTW you should not include two questions in one. – hnwoh Commented Mar 23 at 20:41
  • 1 For a better understanding, I have modified the question. In the someFunction, I am using Repo() along with other code. In order to test other section of the code which is required, I want to mock Repo(). The second question was not a big question. That is why I added within the same question. – Shiva Shukla Commented Mar 24 at 21:21
  • I edited my answer, so now it includes an answer to your main question. – hnwoh Commented Mar 24 at 21:55
Add a comment  | 

1 Answer 1

Reset to default 0

Answering your first question, the correct way to mock with @patch decorator is to pass the correct target namespace as a first argument. So, instead of @patch('git.repo.base.Repo'), you should pass the class Repo with your script's namespace, so assuming your someFunction() to test is placed in someScript.py script, which is placed in someModule module and imports class Repo, the correctly patched test would look like this:

@patch('someModule.someScript.Repo')
def test_some_function(self, mock):
    # test code

There is a special documentation part which touches upon this issue, I strongly recommend you to read it. You can also see a similar question and its answer.

Regarding second question, @mock.patch.object decorators work like all other Python decorators (link to question about Python decorators). When stacked, they are applied from bottom to top, so after editing your example to make it proper Python (@mock.patch.object requires two parameters):

class A:
    def __init__(self):
        self.a = 'a'
        self.b = 'b'
        self.c = 'c'

a = A()

class ATest(TestCase):

    @mock.patch.object(a, 'a')
    @mock.patch.object(a, 'b')
    @mock.patch.object(a, 'c')
    def test_something(self, mocker1, mocker2, mocker3):
        # test code...

mocker1 refers to mocked attribute c, mocker2 to attribute b and mocker3 to attribute a. That's because @ decorator syntax is translated to:

test_a = mock.patch.object(a, 'a')(mock.patch.object(a, 'b')(mock.patch.object(a, 'c')(test_a)))

So you can see that c decorator is the most nested, so it's applied as the first one (even though it is defined as a last one). That's why (maybe a bit counterintuitively) decorator which is defined last is assigned to first parameter of a test function.

本文标签: How can we mock an Object instantiation in pythonStack Overflow