Using pytest monkeypatch to a mock function
Pytest is a widely used testing library. A feature that has helped me every now and then is monkeypatch.
Here are a couple of examples mocking a function output.
For example, lets say that we want to test a function in the code which retrieves data from an external api and process it. To speed up the testing environment and reduce the flakiness we can mock the reponse from the external service. This can be done with:
import external_service.requests
from mock_constants import EXTENAL_PRICES
from important_functions import function_to_test
def test_function_a(monkeypatch):
monkeypatch.setattr(
external_service.requests,
"get_prices",
lambda *args, **kwargs: EXTENAL_PRICES
)
processed_data = function_to_test()
assert processed_data.attr_a == EXTENAL_PRICES.attr_a
...
Note that the third argument of monkeypatch.setattr is a function. On the example above the lambda accepts any arguments, ignores them and returns a fix value. However, the mocked function could process the inputs.
Mocked function can process arguments
Note that the mocked function argument names must match those from the real function
import external_service.requests
from mock_constants import EXTENAL_PRICES, INTERNAL_PRICES
from important_functions import function_to_test
def test_function_a(monkeypatch):
def mocked_fn(arg1):
# Note that the argument names must match
# those from the real function
if arg1 is True:
return EXTENAL_PRICES
else:
return INTERNAL_PRICES
monkeypatch.setattr(
external_service.requests,
"get_prices",
mocked_fn
)
processed_data = function_to_test()
assert processed_data.attr_a == EXTENAL_PRICES.attr_a
assert processed_data.attr_a != INTERNAL_PRICES.attr_a
...
This can be useful for creating paramatrized tests.