schireson / pytest-mock-resources

Pytest Fixtures that let you actually test against external resource (Postgres, Mongo, Redshift...) dependent code.
https://pytest-mock-resources.readthedocs.io/en/latest/quickstart.html
MIT License
179 stars 19 forks source link

Getting errors when using `create_redis_fixture` #187

Closed miguelsousa closed 1 year ago

miguelsousa commented 1 year ago

Describe the bug I'm trying to use pytest-mock-resources for the first time to mock a Redis client. I've used the instructions at https://pytest-mock-resources.readthedocs.io/en/latest/redis.html as a guidance, but I'm running into errors. Not sure if they're caused by bugs, or if I'm doing something wrong with the API. Thanks in advance.

Environment

To Reproduce Steps to reproduce the behavior:

  1. Save the two snippets below as myapp.py and test_myapp.py
  2. Run python -m pip install pytest redis pytest-mock-resources to install the necessary dependencies
  3. Run python -m pytest

Expected behavior The two tests — test_set_item and test_set_item2 — contained in test_myapp.py should succeed.

Actual Behavior Both tests fail. The result is shown below.

FAILED test_myapp.py::test_set_item - AttributeError: 'function' object has no attribute 'hset'
ERROR test_myapp.py::test_set_item2 - AttributeError: 'function' object has no attribute 'pmr_credentials'

Additional context Contents of myapp.py

from redis import Redis

REDIS_CLIENT = Redis(host='localhost', port=6379, db=0)
REDIS_KEY = "some:key"

def set_item(idx, value):
    REDIS_CLIENT.hset(REDIS_KEY, idx, value)

Contents of test_myapp.py

from unittest.mock import patch

import pytest
from pytest_mock_resources import create_redis_fixture
from redis import Redis

from myapp import set_item, REDIS_KEY

@pytest.fixture
def redis_client_fixt():
    yield create_redis_fixture()

def test_set_item(redis_client_fixt):
    with patch('myapp.REDIS_CLIENT', redis_client_fixt) as redis_client:
        idx = 1234
        value = "some_value"
        set_item(idx, value)

        assert redis_client.hget(REDIS_KEY, idx) == value

@pytest.fixture
def redis_client_fixt2():
    redis = create_redis_fixture()
    yield Redis(**redis.pmr_credentials.as_redis_kwargs())

def test_set_item2(redis_client_fixt2):
    with patch('myapp.REDIS_CLIENT', redis_client_fixt2) as redis_client:
        idx = 1234
        value = "some_value"
        set_item(idx, value)

        assert redis_client.hget(REDIS_KEY, idx) == value
DanCardin commented 1 year ago

the fixture is returned directly from create_redis_fixture(), so you would replace your fixture with it. like so:

redis_client = create_redis_fixture()

@pytest.fixture
def redis_client2(redis_client):  # or if you want/need to create your own client object from credentials
    yield Redis(**redis_client.pmr_credentials.as_redis_kwargs())
miguelsousa commented 1 year ago

@DanCardin thanks for the feedback. Here's an updated test_myapp.py that works:

from unittest.mock import patch
from pytest_mock_resources import create_redis_fixture
from myapp import set_item, REDIS_KEY

redis_client_fixt = create_redis_fixture()

def test_set_item(redis_client_fixt):
    with patch('myapp.REDIS_CLIENT', redis_client_fixt) as redis_client:
        idx = 1234
        value = b"some_value"
        set_item(idx, value)

        assert redis_client.hget(REDIS_KEY, idx) == value

It's worth mentioning that the module python_on_whales had to be installed (python -m pip install python-on-whales) and a redis Docker image was pulled the first time the test ran.

DanCardin commented 1 year ago

you can ensure python_on_whales is installed by using the "docker" extra (i.e. pip install pytest-mock-resources[docker]