3

I have a flask application, in which I use "flask-caching" with redis. I save some values in the cache and retrieve it for processing. I have to write unittest for this. How can I mock the redis instance and pass the host for that server in the flask caching config.

I did try "fakeredis", but that does not give me the redis host, which I can use in flask caching and test my application.

How can I go about writing unit test cases for this ?

def func_1():
    # some steps
    x = func2() # this is where the code for flask caching (redis) data retrieval is
    # process x

I have to test func_1()

Simplecode
  • 559
  • 7
  • 19
  • Mock out the calls to redis and assert the correct methods were called on the mock – Iain Shelvington Dec 31 '20 at 10:51
  • One of the functions I have to test have code related to flask caching for retrieving the data and processing it. So, I won't be able to write unit tests for that. Don't have different function to just retrieve redis data. – Simplecode Dec 31 '20 at 10:56

1 Answers1

3

The mock object library can be used to create a Mock instance for Redis that returns a value for a particular method call, for example:

from unittest.mock import Mock

def test_redis():
    mock_redis = Mock()
    mock_redis.get.return_value = "2020-12-31T00:00:00".encode()

    function_to_test(mock_redis)

If a function needs to be mocked, so that the function is not actually called, and is used inside the function that is being tested, the patch decorator can be used, as follows:

from unittest.mock import patch

@patch("package.module.function_to_mock")
def test_redis(mock_function_to_mock):
    mock_function_to_mock.get.return_value = "2020-12-31T00:00:00".encode()

    function_to_test()

This could be used to mock the flask caching related code that is inside the function that you are testing.


Edit

For your case, I believe you may want to do the following:

from unittest.mock import patch

@patch("package.module.func2")
def test_func_1(mock_func2):
    mock_func2.return_value = "Test value"

    func_1()

    mock_func2.assert_called_once()

Here func2() is mocked and it's return value is set to "Test value", so when it is called inside of func_1() variable x equals "Test value"

Note: the path passed to patch() must be to where func2() is imported, and not to the module where func2() is defined.

consoledotlog
  • 124
  • 1
  • 9
  • Can you pls. explain the difference between function_to_mock and mock_function_to_mock in the second example ? – Simplecode Dec 31 '20 at 12:45
  • @Simplecode `function_to_mock` is the target function to mock, so that it's not actually called. I believe for your case `function_to_mock` is `func2()`. `mock_function_to_mock` is the `MagicMock` instance created by `patch()` for `function_to_mock`. In other words, `patch()` replaces `function_to_mock` with a `MagicMock` instance, which is then passed to the test function `test_redis()` via the `mock_function_to_mock` parameter. `mock_function_to_mock` can then be used to specify returned values. – consoledotlog Dec 31 '20 at 16:04
  • Is this necessary to use ```mock_func2.assert_called_once() ? ``` – Simplecode Jan 04 '21 at 11:50
  • 1
    @Simplecode It's not necessary to call `mock_func2.assert_called_once()` as it only checks that `func2` is called only once inside of `func_1()`. If you don't want to check this, then it can be left out. – consoledotlog Jan 04 '21 at 12:41