Reputation: 311
I have the following (simplified) piece of code:
def get_redis()
return redis_instance
def bar(key, value, redis=get_redis())
redis.set(key, value)
def foo()
bar("key", value)
In my test I want to mock the function get_redis
to return an instance of fakeredis.FakeStrictRedis()
, so I did this
def test_foo(mocker):
mocker.patch("app.main.get_redis", return_value=fakeredis.FakeStrictRedis())
foo()
the mocked function has no effect, the foo
function try to connect to real redis using the get_redis function from main.
If I wrote in this way works
def bar(key, value)
redis=get_redis()
redis.set(key, value)
This works, but I can pass redis as default value. How can I mock?
Upvotes: 3
Views: 366
Reputation: 1015
There's nothing wrong with your mock, but you seem to be misunderstanding how default parameter values work. As explained in the Python Language Reference, default parameter values are evaluated when the function definition is executed.
In your case, this means that the original get_redis
is called already when bar
is defined:
def bar(key, value, redis=get_redis()):
This statement is executed when pytest
imports your module, i.e., before test_foo
is executed, so mocking get_redis
in the test has no effect because it's already too late by then.
To make the default-supplying factory function mockable, use None
as the default and make the function call the factory unless another value was specified in the call:
def bar(key, value, redis=None)
redis = redis or get_redis()
redis.set(key, value)
Upvotes: 1
Reputation: 15926
I would just modify the bar
function slightly as follows so that your functions don't get called before the mock can be applied:
def bar(key, value, redis=get_redis)
if callable(redis):
redis = redis()
redis.set(key, value)
Writing the function this way means that your mock will apply at the time the function is called, and not at startup before any mocks can be applied. In short, writing bar
this way, ensures the return of get_redis
it will propagate through your bar
function every time the function is called .
Upvotes: 2