Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can not mock rq's redis connection with mockredis #282

Closed
zgoda opened this issue Nov 14, 2013 · 7 comments
Closed

Can not mock rq's redis connection with mockredis #282

zgoda opened this issue Nov 14, 2013 · 7 comments

Comments

@zgoda
Copy link

zgoda commented Nov 14, 2013

Because of check if connection is instance of StrictRedis in rq.compat.connection.patch_connection(). Is this check really necessary?

@wuub
Copy link
Contributor

wuub commented Nov 22, 2013

If it helps anything, this is how I mock redis with RQ:

import redis
import fakeredis

class VeryFakeStrictRedis(fakeredis.FakeStrictRedis, redis.StrictRedis):
     pass

It haven't backfired yet :)

@robodude666
Copy link

@wuub Might be a difference in how we're trying to use the VeryFakeStrictRedis mock, but I also find the need to still patch patch_connection. This is because rq maps pipeline to _pipeline from redis.StrictRedis. This prevents Worker.work from being used in burst-mode in your tests.

I still think it would be beneficial to improve rq's mock-ability. For instance, what is the need for patch_connection? I see that it provides StrictRedis mappings of certain methods to the Redis instance, but is that really necessary? I can't seem to find any docs suggesting pipeline is different between Redis and StrictRedis.

In addition, it's also impossible to use mock.patch to patch redis.Redis and rq.Queue and simply find out if enqueue was called with the expected arguments... or do anything if you don't have a 100% authentic StrictRedis or Redis connection. Looking through the rq test suite, that isn't an issue because it expects a live redis instance running.

@yrik
Copy link

yrik commented Jan 21, 2015

@robodude666 could you show how you patch patch_connection?
I have the same issue..

@homeworkprod
Copy link
Contributor

I struggle with this as well. Bummer.

@homeworkprod
Copy link
Contributor

For my simple use case – avoiding the need for a running Redis server during tests – without any mock call verifications, this seems to work (Python 3.4.2, redis 2.10.3, rq 0.5.2):

from unittest.mock import MagicMock

from redis import StrictRedis


class StrictRedisMock(MagicMock, StrictRedis):

    @classmethod
    def from_url(cls, arg):
        return cls()

The code under test creates StrictRedis instances via the from_url method. YMMV.

Apply like this:

class SomeTest(SomeTestBase):

    @patch('redis.StrictRedis.from_url', StrictRedisMock.from_url)
    def setUp(self):
        super().setUp()

        # …

HTH

@nvie nvie closed this as completed Jun 3, 2015
@homeworkprod
Copy link
Contributor

For the record, I switched from the mock class using diamond inheritance to this:

def strict_redis_client_from_url(url):
    mock = MagicMock()
    mock.__class__ = StrictRedis
    return mock

Usage:

class SomeTest(SomeTestBase):

    @patch('redis.StrictRedis.from_url', strict_redis_client_from_url)
    def setUp(self):
        super().setUp()

        # …

That said, my two suggested approaches might have serious limitations I haven't (yet) hit.

@nvie
Copy link
Collaborator

nvie commented Jun 3, 2015

I wish there was a better way for me to check this in patch_connection, but I don't think there is another way of distinguishing between redis.StrictRedis and redis.Redis other than using explicit isinstance() checks. If anyone has a better suggestion, I'd like to hear it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants