33

I just found that a bunch of unit tests are failing, due a developer hasn't mocked out the dependency to a redis client within the test. I'm trying to give a hand in this matter but have difficulties myself.

The method writes to a redis client:

redis_client = get_redis_client()
redis_client.set('temp-facility-data', cPickle.dumps(df))

Later in the assert the result is retrieved:

res = cPickle.loads(get_redis_client().get('temp-facility-data'))
expected = pd.Series([set([1, 2, 3, 4, 5])], index=[1])
assert_series_equal(res.variation_pks, expected)

I managed to patch the redis client's get() and set() successfully.

@mock.patch('redis.StrictRedis.get')
@mock.patch('redis.StrictRedis.set')
def test_identical(self, mock_redis_set, mock_redis_get):
    mock_redis_get.return_value = ???
    f2 = deepcopy(self.f)
    f3 = deepcopy(self.f)
    f2.pk = 2
    f3.pk = 3
    self.one_row(f2, f3)

but I don't know how to set the return_value of get() to what the set() would set in the code, so that the test would pass.

Right now this line fails the test:

res = cPickle.loads(get_redis_client().get('temp-facility-data'))
TypeError: must be string, not MagicMock

Any advice please?

1

3 Answers 3

29

Think you can use side effect to set and get value in a local dict

data = {}
def set(key, val):
    data[key] = val

def get(key):
    return data[key]

mock_redis_set.side_effect = set
mock_redis_get.side_effect = get

not tested this but I think it should do what you want

Sign up to request clarification or add additional context in comments.

2 Comments

Can you give a little bit more context? (write a complete test, with mock creation, actual get/set usage in a code that you test). Also, how do you prevent connection from crashing, I guess that even if you mock get/set, pool connections (and any other network related connection) will still crash.
Thank you for sharing. I found out that using get is better since using a non-existing key on REDIS does not raise exception. ``` def get(key): return data.get(key) ```
8

If you want something more complete, you can try fakeredis

@patch("redis.Redis", return_value=fakeredis.FakeStrictRedis())
def test_something():
....

1 Comment

"Fakeredis has moved". New maintainer: github.com/cunla/fakeredis-py
1

I think you can do something like this.

redis_cache = {
    "key1": (b'\x80\x04\x95\x08\x00\x00\x00\x00\x00\x00\x00\x8c\x04test\x94.', "test"),
    "key2": (None, None),
}
    
def get(redis_key):
    if redis_key in redis_cache:
        return redis_cache[redis_key][0]
    else:
        return None
    
mock = MagicMock()
mock.get = Mock(side_effect=get)
    
with patch('redis.StrictRedis', return_value=mock) as p:
    for key in redis_cache:
        result = self.MyClass.my_function(key)
        self.assertEqual(result, redis_cache[key][1])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.