I am using redis in the following way:
from redis import Redis
redis_client = Redis()
def get_datetime_from_redis(key):
start_time = redis_client.get(key)
start_time = datetime.strptime(datetime_as_string, "%Y-%m-%d %H:%M:%S.%f")
duration = (datetime.now() - start_time).total_seconds()
return duration
I'd like to test the function in the following way:
import pytest
from core.utils import get_datetime_from_redis
from unittest.mock import Mock
from datetime import datetime
def test_get_datetime_from_redis(monkeypatch):
mock_redis = Mock()
mock_redis.get.return_value = datetime(2022, 1, 26)
monkeypatch.setattr('core.utils.Redis', mock_redis)
get_datetime_from_redis('foo')
mock_redis.get.assert_called_once()
But the issue is that by the time that monkeypatch.setattr('core.utils.Redis', mock_redis) is run, redis_client is already instantiated, so I'm not mocking the correct version.
How do I address these kinds of tests?
CodePudding user response:
Not sure it will solve entirely the problem but you should design your tests to have a fixture in charge of managing the creation of the mocked redis (mock_redis). By encapsulating this code in a fixture you will be able to manage when the fixture is created (once per session, per module, per function) and to gather all this code at a single location.
Here is a good example on how to do that.
Second point is on the way you instantiate redis_client client in your code. Since it's not done in a method or in a class, redis_client is created as soon as the module is imported. You should also consider deferring the instantiation by putting it in a method or class you can call when needed.
CodePudding user response:
Since the function is consuming the global variable of the module, your monckeypatch should mock it.
So :
import pytest
from core.utils import redis_client
from core.utils import get_datetime_from_redis
from datetime import datetime
def test_get_datetime_from_redis(monkeypatch):
redis_get_called = []
def mock_redis_get(key) :
get_called.append(1) # Add to call count
return datetime(2022, 1, 26)
monkeypatch.setattr(redis_client, 'get', mock_redis_get)
get_datetime_from_redis('foo')
assert len(redis_get_called) == 1
