redispython-unittestpython-mockpython-unittest.mockdjango-redis

How to write python unittest cases to mock redis connection (redis.StrictRedis) in Django


How can I mock the following function for connecting to Redis?

import redis

class RedisCache:
    redis_instance = None

    @classmethod
    def set_connect(cls):
        redis_instance = redis.StrictRedis(host='0.0.0.0', port=6379, password='xyz', charset='utf-8', decode_responses=True, socket_timeout=30)
        return redis_instance

    @classmethod
    def get_conn(cls):
        cls.redis_instance = cls.set_connect()
        return cls.redis_instance

I looked for some solutions, but they were basically using fakeredis module. I wanted to have a simpler way to mock these functions.

Note- data returned by the function: Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>


Solution

  • You can use patch() function to mock out redis.StrictRedis class. See where-to-patch

    E.g.

    redis_cache.py:

    import redis
    
    
    class RedisCache:
        redis_instance = None
    
        @classmethod
        def set_connect(cls):
            redis_instance = redis.StrictRedis(host='0.0.0.0', port=6379, password='xyz',
                                               charset='utf-8', decode_responses=True, socket_timeout=30)
            return redis_instance
    
        @classmethod
        def get_conn(cls):
            cls.redis_instance = cls.set_connect()
            return cls.redis_instance
    

    test_redis_cache.py:

    from unittest import TestCase
    import unittest
    from unittest.mock import patch, Mock
    from redis_cache import RedisCache
    
    
    class TestRedisCache(TestCase):
        def test_set_connect(self):
            with patch('redis.StrictRedis') as mock_StrictRedis:
                mock_redis_instance = mock_StrictRedis.return_value
                actual = RedisCache.set_connect()
                self.assertEqual(actual, mock_redis_instance)
                mock_StrictRedis.assert_called_once_with(host='0.0.0.0', port=6379, password='xyz',
                                                         charset='utf-8', decode_responses=True, socket_timeout=30)
    
        @patch('redis.StrictRedis')
        def test_get_conn(self, mock_StrictRedis):
            mock_redis_instance = mock_StrictRedis.return_value
            RedisCache.get_conn()
            self.assertEqual(RedisCache.redis_instance, mock_redis_instance)
    
    
    if __name__ == '__main__':
        unittest.main()
    

    test result:

    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.004s
    
    OK
    Name                                             Stmts   Miss  Cover   Missing
    ------------------------------------------------------------------------------
    src/stackoverflow/70016401/redis_cache.py           11      0   100%
    src/stackoverflow/70016401/test_redis_cache.py      18      0   100%
    ------------------------------------------------------------------------------
    TOTAL                                               29      0   100%