In Pytest, Is there a way to "mock" or prevent something from happening while collecting test?
Question:
So assume the allowing :
# services/foo.py
from apps.bar import BarClass
static_foos = BarClass().get_statics()
class FooService() :
....
and test code looking like :
# tests/test_foo.py
from services.foo import FooService
def test_foo_something() :
assert FooService.something() == True
So here, when the pytest collects the test, it seems like it executes BarClass.get_statics()
even before any of my attempts to mock or block access in conftest.py
to kick in.
To be more specific, assuming get_statics()
has some requests.get
in it, a typical way of blocking network in pytest, which is mocking socket.socket
, is not working.
From my knowledge, the only way to do something before tests get collected is to use pytest_configure
in conftest.py
, but also AFAIK it doesn’t allow me to mock meaning that I’m just completely losing hope right now (Also it’s not like I can really change the content of test_something
for various reasons).
Is there any possible solution in this case?
Answers:
You can import the services.foo
module within the test function instead, after you monkey-patch requests.get
:
import requests
# define your MockResponse class here
def test_foo_something(monkeypatch):
def mock_get(*args, **kwargs):
return MockResponse()
monkeypatch.setattr(requests, "get", mock_get)
from services.foo import FooService
assert FooService.something() == True
You can import BarClass
from apps.bar
right before importing FooService
and mock the get_statics
. For example:
from apps.bar import BarClass
def do_nothing(*args, **kwargs):
pass
BarClass.get_statics = do_nothing
from services.foo import FooService
def test_foo_something() :
assert FooService.something() == True
However I think it would be better to add some initializing function to services.foo
and call it when its needed. Something like:
from apps.bar import BarClass
static_foos = None
def init():
static_foos = BarClass().get_statics()
class FooService():
...
So assume the allowing :
# services/foo.py
from apps.bar import BarClass
static_foos = BarClass().get_statics()
class FooService() :
....
and test code looking like :
# tests/test_foo.py
from services.foo import FooService
def test_foo_something() :
assert FooService.something() == True
So here, when the pytest collects the test, it seems like it executes BarClass.get_statics()
even before any of my attempts to mock or block access in conftest.py
to kick in.
To be more specific, assuming get_statics()
has some requests.get
in it, a typical way of blocking network in pytest, which is mocking socket.socket
, is not working.
From my knowledge, the only way to do something before tests get collected is to use pytest_configure
in conftest.py
, but also AFAIK it doesn’t allow me to mock meaning that I’m just completely losing hope right now (Also it’s not like I can really change the content of test_something
for various reasons).
Is there any possible solution in this case?
You can import the services.foo
module within the test function instead, after you monkey-patch requests.get
:
import requests
# define your MockResponse class here
def test_foo_something(monkeypatch):
def mock_get(*args, **kwargs):
return MockResponse()
monkeypatch.setattr(requests, "get", mock_get)
from services.foo import FooService
assert FooService.something() == True
You can import BarClass
from apps.bar
right before importing FooService
and mock the get_statics
. For example:
from apps.bar import BarClass
def do_nothing(*args, **kwargs):
pass
BarClass.get_statics = do_nothing
from services.foo import FooService
def test_foo_something() :
assert FooService.something() == True
However I think it would be better to add some initializing function to services.foo
and call it when its needed. Something like:
from apps.bar import BarClass
static_foos = None
def init():
static_foos = BarClass().get_statics()
class FooService():
...