[Python] How to mock an Enum in pytest globally

Discussão em 'Python' iniciado por Stack, Dezembro 7, 2024.

  1. Stack

    Stack Membro Participativo

    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.

    Continue reading...

Compartilhe esta Página