Flask: Mock call to external component returns a non serializable object for a HTTP response
Question: I'm trying to learn how to use the Mock library in python.

I have a Flask application which is connected to Redis via redis-py package.

In the '/myapp/version' API of my app, I call a info() from redis-py, and
format a HTTP response back where the JSON data includes also the return data
from the info() call:

    
    
    from flask import Flask, jsonify
    from redis import StrictRedis
    
    app = Flask(__name__)
    redis = StrictRedis(host='redis', port=6379)
    
    @app.route('/myapp/version', methods=['GET'])
    def get_version():
        redis_info = redis.info() #returns a dict
        return jsonify({
            'app_version': '0.1',
            'flask_version': '0.11.1',
            'redis_info': redis_info
        })
    

And this is my test.py, which uses the Flask test_client:

    
    
    import json
    import mock
    import redis
    import myapp import app
    
    class TestApp:
        @classmethod
        def setup_class(self):
            self.client = app.test_client()
            self.client.testing = True
    
        @mock.patch.object(redis.StrictRedis, 'info')
        def test_get_version(self, mock_info):
            result = self.client.get('/myapp/version')
            assert result.status_code == 200
            mock_info.assert_called()
    

If I launch nosetests, the response from the HTTP request will return error:

    
    
    TypeError: <MagicMock name='info()' id='140548379595472'> is not JSON serializable
    

I guess that the problem is that the info() call is correctly mocked, but then
it cannot be serialzed to JSON to format the response by the Flask test
client.

Is there a way to get a valid response anyway? Or maybe I am using Mock in the
wrong way? I know it is handy in unit test but here it'm more like integration
testing.


Answer: The best way to mock `redis-py` package is ti use `mockredis`. You need to
simply patch your method using: `@patch('redis.StrictRedis',
mock_strict_redis_client)`. More info can be found on the project
[page](https://github.com/locationlabs/mockredis).

Once you patched `redis`, you can setup the value of specific keys required
for your application as if you're using `redis`. This will enable you to
control what values should be returned from the various redis calls and will
ensure that your application will work properly.

In your specific case, the call for redis that is being done somewhere in your
app might be returning the magic mock instead of some serializable `json`.

You can control the return value of the call by using `mock_info.return_value
= json_str`

