4

I implemented a Redis cache in my Flask app using Flask-Caching==1.3.3, but obviously some of my endpoint unit tests are now failing because the responses are cached, making some POST/PUT tests fail.

Is there some good way to disable the cache during unit tests? I'm using pytest==3.5.0

Eg. this fails because the old entry is returned from cache:

   def test_updating_biography(self):
        """Should update the current newest entry with the data in the JSON."""
        response = self.app.put(
            "/api/1.0/biography/",
            data=json.dumps(
                dict(
                    short="UnitTest Updated newest short",
                    full="UnitTest Updated newest full",
                )
            ),
            content_type="application/json"
        )

        get_bio = self.app.get("/api/1.0/biography/")
        biodata = json.loads(get_bio.get_data().decode())

        self.assertEquals(200, response.status_code)
        self.assertEquals(200, get_bio.status_code)
>       self.assertEquals("UnitTest Updated newest short", biodata["biography"][0]["short"])
E       AssertionError: 'UnitTest Updated newest short' != 'UnitTest fourth short'
E       - UnitTest Updated newest short
E       + UnitTest fourth short

tests/biography/test_biography_views.py:100: AssertionError

I tried for example:

def setUp(self):
    app.config["CACHE_TYPE"] = None
    app.config["CACHE_REDIS_URL"] = ""
    self.app = app.test_client()

And also app.config["CACHE_TYPE"] = "null" and app.config["CACHE_TYPE"] = "", but it is still using the cache in the unit test.

I tried this one, but it's of course outside of app context:

@cache.cached(timeout=0)
def test_updating_biography(self):
2
  • Not sure if this is helpful, but when testing apps that use celery/redis, we configure celery to use an in-memory broker. In absence of a solution for disabling caching, perhaps you could consider using a setup or teardown method to clear the cache.
    – sytech
    Commented Mar 23, 2018 at 14:26
  • @sytech: Ah, that's a great idea since I only test a single app with this redis. Commented Mar 23, 2018 at 14:34

1 Answer 1

4

As mentioned in the comment, sytech's idea works for me since I only test a single app with this redis. Obviously if you use a shared redis for multiple apps, this might not work for you. But for my case, it worked perfectly and can be repeated without issues:

import unittest

from flask_caching import Cache
from app import app, db


class TestBiographyViews(unittest.TestCase):
    def setUp(self):
        """Add some test entries to the database, so we can test getting the latest one."""

        # Clear redis cache completely
        cache = Cache()
        cache.init_app(app, config={"CACHE_TYPE": "redis"})
        with app.app_context():
            cache.clear()

        self.app = app.test_client()

The above is all you need. The rest of the test cases can be as normal. Works for me.

4
  • Actually, it's not 100 % perfect yet. When I run the full test suite, this does not clear the cache all the time for some reason. Maybe it does not clear it fast enough until a new test begins? Commented Mar 24, 2018 at 7:27
  • Scratch that, one cleanup commit was accidentally deleted in one tearDown of the local branch, which rippled to multiple tests. Commented Mar 24, 2018 at 12:38
  • Hi, How can i apply this to the test itself? Like i have this test and i want to clear is cache: @patch("dev_maintenance.machines.get_azure_compute_client") def test_get_azure_machine_info (get_azure_compute_client): with app.app_context(): ret = get_azure_machine_info("hdfs-test-eu-w","test-eu-w-01") assert (ret == get_azure_compute_client.return_value.virtual_machines.get.return_value) get_azure_compute_client.return_value.virtual_machines.get.assert_called_once_with( "rg1", "m1", expand="instanceView") Commented Feb 7, 2020 at 13:16
  • @PatrickJosé You can also call the above within the test, eg. act, assert, clear cache, act, assert. If you do it multiple times, I would move it to a helper function. Commented Aug 31, 2020 at 8:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.