Ghasem
Ghasem

Reputation: 15613

How to pass pytest fixture to the main function without adding it to parameters?

In my project I have a Settings class:

config.py

class Settings(BaseSettings):
    DEBUG: bool = os.getenv("DEBUG", 'False')
    TOKEN_KEY: str = os.getenv("TOKEN_KEY", '')
    TOKEN_PASSWORD: str = os.getenv("TOKEN_PASSWORD", '')


@lru_cache()
def get_settings():
    return Settings()

And I'm using it in a method like this:

helpers.py

def generate_new_token(user: User) -> str:
   
    settings = get_settings()
    private_key = settings.TOKEN_KEY
    token_password = settings.TOKEN_PASSWORD
    # Do something

I've created these two fixtures:

conftest.py

@pytest.fixture
def get_settings():
    return Settings(DEBUG=True, TOKEN_KEY="SOME_FAKE_TOKEN_KEY", TOKEN_PASSWORD='')

@pytest.fixture
def get_user():
    return User()

Now I want to test the generate_new_token method with the values returned from fixtures:

test_helpers.py

def test_generate_new_token(get_user, get_settings):
    generate_new_token(user=get_user)

In this case, the TOKEN_KEY value from get_settings should be SOME_FAKE_TOKEN_KEY, but it's still empty.

When I debug the code, I can see that it passes the value from get_settings fixture to test_generate_new_token , but then generate_new_token calls the main get_settings method and does not use the get_settings value from fixture as settings value.

I know that if I pass settings as a parameter to generate_new_token like this:

def generate_new_token(user: DexterUser, settings: Settings) -> str:

I can then pass the fixture to it from test function:

def test_generate_new_token(get_user, get_settings):
    generate_new_token(user=get_user, settings=get_settings)

But is there anyway to pass the fixture to the main function without having to add it to its parameters?

Upvotes: 0

Views: 1097

Answers (1)

MrBean Bremen
MrBean Bremen

Reputation: 16855

Your fixture does not replace the function get_settings, it is just another implementation. What you need to do is to patch the implementation with your own, for example:

conftest.py

from unittest import mock
import pytest

@pytest.fixture
def get_settings():
    with mock.patch("your_module.helpers.get_settings") as mocked_settings:
        mocked_settings.return_value = Settings(
            DEBUG=True,                                               
            TOKEN_KEY="SOME_FAKE_TOKEN_KEY",                                               
            TOKEN_PASSWORD='')
        yield

Note that you have to mock the reference of get_settings that is imported in your helpers module, see where to patch.

Upvotes: 1

Related Questions