First of all, the relevant portion of my project directory looks like:
└── my_package
├── my_subpackage
│ ├── my_module.py
| └── other_module.py
└── tests
└── my_subpackage
└── unit_test.py
I am writing some tests in unit_test.py
that require mocking of an external resource at the module level. I would like to use a pytest fixture
with module level scope and pytest monkeypatch
to acomplish this. Here is a snippet of what I have tried in unit_test.py
:
import unittest.mock as mock
import pytest
from my_package.my_subpackage.my_module import MyClass
@pytest.fixture(scope='function')
def external_access(monkeypatch):
external_access = mock.MagicMock()
external_access.get_something = mock.MagicMock(
return_value='Mock was used.')
monkeypatch.setattr(
'my_package.my_subpackage.my_module.ExternalAccess.get_something',
external_access.get_something)
def test_get_something(external_access):
instance = MyClass()
instance.get_something()
assert instance.data == 'Mock was used.'
Everything works just fine. But when I try to change line 8 from @pytest.fixture(scope='function')
to @pytest.fixture(scope='module')
, I get the following error.
ScopeMismatch: You tried to access the 'function' scoped fixture 'monkeypatch' with a 'module' scoped request object, involved factories
my_package\tests\unit_test.py:7: def external_access(monkeypatch)
..\..\Anaconda3\envs\py37\lib\site-packages\_pytest\monkeypatch.py:20: def monkeypatch()
Does anyone know how to monkeypatch with module level scope?
In case anyone wants to know, this is what the two modules look like as well.
my_module.py
from my_package.my_subpackage.other_module import ExternalAccess
class MyClass(object):
def __init__(self):
self.external_access = ExternalAccess()
self.data = None
def get_something(self):
self.data = self.external_access.get_something()
other_module.py
class ExternalAccess(object):
def get_something(self):
return 'Call to external resource.'
I found this issue which guided the way. I needed to make a few changes to the solution for module level scope. unit_test.py
now looks like this:
import unittest.mock as mock
import pytest
from my_package.my_subpackage.my_module import MyClass
@pytest.fixture(scope='module')
def monkeymodule():
from _pytest.monkeypatch import MonkeyPatch
mpatch = MonkeyPatch()
yield mpatch
mpatch.undo()
@pytest.fixture(scope='module')
def external_access(monkeymodule):
external_access = mock.MagicMock()
external_access.get_something = mock.MagicMock(
return_value='Mock was used.')
monkeymodule.setattr(
'my_package.my_subpackage.my_module.ExternalAccess.get_something',
external_access.get_something)
def test_get_something(external_access):
instance = MyClass()
instance.get_something()
assert instance.data == 'Mock was used.'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With