In a rather complex test scenario I need to mock the base class of one of my own classes and instantiate the latter several times. When I do that my test errors with a StopIteration
exception. Here's what my scenario boils down to in this respect:
Code under test (my_class.py
):
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session
class MySession(OAuth2Session):
pass
class MyClass:
def init(self, x):
self.x = x
client = BackendApplicationClient(client_id=x)
self.session = MySession(client=client)
Test code (test_mock.py
):
import unittest
from unittest.mock import patch
with patch('requests_oauthlib.OAuth2Session') as MockSession:
from my_class import MyClass
cls = MyClass()
class MockTest(unittest.TestCase):
def test_mock_1(self):
cls.init(1)
self.assertIsNotNone(cls.session)
def test_mock_2(self):
cls.init(2)
self.assertIsNotNone(cls.session)
Test result:
$ python -m unittest test_mock
.E
======================================================================
ERROR: test_mock_2 (test_mock.MockTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "...\test_mock.py", line 16, in test_mock_2
cls.init(2)
File "...\my_class.py", line 11, in init
self.session = MySession(client=client)
File "C:\Python39\lib\unittest\mock.py", line 1093, in __call__
return self._mock_call(*args, **kwargs)
File "C:\Python39\lib\unittest\mock.py", line 1097, in _mock_call
return self._execute_mock_call(*args, **kwargs)
File "C:\Python39\lib\unittest\mock.py", line 1154, in _execute_mock_call
result = next(effect)
StopIteration
----------------------------------------------------------------------
Ran 2 tests in 0.003s
FAILED (errors=1)
I have debugged into the unittest.mock.MagicMock
class but I can't figure out what's going on. In MagicMock's _execute_mock_call()
method I noticed that self.side_effect
is a tuple iterator object and when next()
is called on that in the second test (test_mock_2
) it results in the StopIteration
.
Both tests run "OK" if I don't use the MySession
subclass, i.e. self.session = OAuth2Session(client=client)
in MyClass' init()
method. (But that's just not how the real code under test works...)
Any ideas anyone?
You should mock class which you directly use, because your custom class inherit Mock and next starts unexpected behavior.
Rewrite path method to your custom class.
import unittest
from unittest.mock import patch
with patch('my_class.MySession') as MockSession:
from my_class import MyClass