2

I am fairly new to Python and having a hard time wrapping my head around how to mock patch API calls in unit testing. FYI, I am using Python 2.7 and using nosetest for my unit testing needs.

I have the following module (myRedis.py) which I want to unit test:

import logging import redis redispool = None class myRedis(object): def __init__(self, redisHost, redisPort, redisDBNum): if not redisPort.isdigit(): raise TypeError('Exception: Expected int for redisPort') if not redisDBNum.isdigit(): raise TypeError('Exception: Expected int for redisDBNum') self._redis_instance = None self._redishost = redisHost self._redisport = redisPort self._redisdb = redisDBNum global redispool redispool = redis.ConnectionPool(host=self._redishost, port=self._redisport, db=self._redisdb) def redis_connect(self): LOGGER.info('Connecting Redis client to %s:%s:%s', self._redishost, self._redisport, self._redisdb) self._redis_instance = redis.StrictRedis(connection_pool=redispool) def write_redis(self, key, value): retval = self._redis_instance.set(key, value) LOGGER.info('Writing data to redis (%s, %s). Retval=%s', key, value, retval) return retval def read_redis(self, key): retval = self._redis_instance.get(key) LOGGER.info('Reading data from redis: key=%s. Retval=%s', key, retval) return retval 

As far as unit testing goes, I have the following so far.

from nose.tools import * import mock from myRedis import myRedis def setup(): pass def teardown(): pass @mock.patch('redis.StrictRedis') def test_mock_redis_StrictRedis(mock_conn_pool): mock_conn_pool.return_value = True assert(True) def test_myRedis(): assert_raises(TypeError, myRedis, 'test', '1234', 'a11') assert_raises(TypeError, myRedis, 'test', 'a1234', '11') myRedisObj = myRedis('localhost', '8888', '11') assert_equal(myRedisObj._redishost, 'localhost') assert_equal(myRedisObj._redisport, '8888') assert_equal(myRedisObj._redisdb, '11') myRedisObj.redis_connect() #oclRedis.read_redis('test') #oclRedis.write_redis('test', 'test') 

I am able to patch the redis.StrictRedis() call without any problems. But how do I patch the redis' get() and set() calls since they are invoked on an object (_redis_instance in myRedis.py). I tried a few different versions of @mock.patch.object, but that didn't work for me. Looking for some guidance.

Thanks in advance.

1 Answer 1

2

What you should patch are not the actual calls from your object but actually the object itself that those calls are invoking.

In your code it would something along the lines of:

from nose.tools import * import mock import unittest from red import myRedis def setup(): pass def teardown(): pass @mock.patch('redis.StrictRedis') def test_mock_redis_StrictRedis(mock_conn_pool): mock_conn_pool.return_value = True assert(True) def test_myRedis_wrong_args(): assert_raises(TypeError, myRedis, 'test', '1234', 'a11') assert_raises(TypeError, myRedis, 'test', 'a1234', '11') def test_myRedis_ok(): myRedisObj = myRedis('localhost', '8888', '11') assert_equal(myRedisObj._redishost, 'localhost') assert_equal(myRedisObj._redisport, '8888') assert_equal(myRedisObj._redisdb, '11') @mock.patch('redis.StrictRedis.set') def test_myRedis_write(mock_strict_redis_set): mock_strict_redis_set.return_value = {} myRedisObj = myRedis('localhost', '8888', '11') redis_connect = myRedisObj.redis_connect() connect = myRedisObj.write_redis('1', '2') assert connect == {} 

As you can see I modified your tests to test one thing at a time. This is something that you generally want to do to avoid side-effects and guarantee test isolation.

Consider taking a look at the docs: https://docs.python.org/dev/library/unittest.mock.html

Finally indenting is key in Python, consider proper indenting in your code snippets going forward

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.