I have a trading bot project, let’s call it trading_bot
. I am using python-binance
. I have an enum
class CoinName(str, Enum):
USDT = "USDT"
BTC = "BTC"
ETH = "ETH"
BNB = "BNB"
XRP = "XRP"
ADA = "ADA"
...
which consists of 100 coin names. I am using it for type hinting, but also via list(CoinName)
to iterate over the coins I am interested to send requests, to get historical prices and to filter my current assets. I want to only use a subset of it for the tests. I am using pytest
and pytest-mock
.
I have a mock like this:
@pytest.fixture
def mock_binance_client(mocker):
mock_client = MockBinanceClient()
mocker.patch("binance.Client", return_value=mock_client)
return mock_client
This is okay as in the tests I use it directly or inject it explicitly. However, I am struggling to mock CoinName
.
So far I found two solutions:
In conftest.py
:
def pytest_configure(config):
from pytest_mock import plugin
mocker = plugin.MockerFixture(config)
mock_definitions = mocker.Mock()
mock_definitions.CoinName = MockCoinName
mocker.patch.dict(
"sys.modules", {"trading_bot.definitions": mock_definitions})
or I need to add from trading_bot.definitions import CoinName
to my project __init__.py
and everywhere I do from trading_bot.definitions import CoinName
I have to change it to import trading_bot
and then use it via trading_bot.CoinName
.
Then if in conftest.py
I mock normally:
@pytest.fixture(autouse=True)
def mock_coin_name(mocker):
patched = mocker.patch(
"trading_bot.definitions.CoinName", MockCoinName)
It works.
However, it doesn’t work if I do the second option and don’t change my importing method, as then other files have another linking to CoinName
, via trading_bot.foo.CoinName
and this gets imported before any fixture runs.
My question:
The first solution feels too hacky and the second one feels too cumbersome. Is there a way to not change how I import in my project but also not hack sys.modules
directly and mock the enum? Or should I structure my code differently, for example not use enums like this?
Thank you in advance.
nontrivial is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.