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 |1 Answer
Reset to default 0Answering 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.
someFunction
is not correct Python. IfsomeFunction
works only withRepo
object, what do you aim to test if you mock theRepo
object? BTW you should not include two questions in one. – hnwoh Commented Mar 23 at 20:41