Repository: django/django
File: tests/cache/tests.py (Python)

Code before:
        with self.assertRaisesMessage(TypeError, msg):
            cache.get_or_set("brian")
        with self.assertRaisesMessage(TypeError, msg):
            cache.get_or_set("brian", version=1)
        self.assertIsNone(cache.get("brian", version=1))
        self.assertEqual(cache.get_or_set("brian", 42, version=1), 42)
        self.assertEqual(cache.get_or_set("brian", 1979, version=2), 1979)
        self.assertIsNone(cache.get("brian", version=3))

    def test_get_or_set_racing(self):
        with mock.patch(
            "%s.%s" % (settings.CACHES["default"]["BACKEND"], "add")
        ) as cache_add:
            # Simulate cache.add() failing to add a value. In that case, the
            # default value should be returned.
            cache_add.return_value = False
            self.assertEqual(cache.get_or_set("key", "default"), "default")

    async def test_async_impl(self):
        if hasattr(cache, "get_many"):
            self.assertTrue(hasattr(cache, "aget_many"))
        if hasattr(cache, "set_many"):
            self.assertTrue(hasattr(cache, "aset_many"))
        if hasattr(cache, "delete_many"):
            self.assertTrue(hasattr(cache, "adelete_many"))


@override_settings(
    CACHES=caches_setting_for_tests(
        BACKEND="django.core.cache.backends.db.DatabaseCache",
        # Spaces are used in the table name to ensure quoting/escaping is
        # working
        LOCATION="test cache table",
    )
)
class DBCacheTests(BaseCacheTests, TransactionTestCase):
    available_apps = ["cache"]

    def setUp(self):
        # The super calls needs to happen first for the settings override.
        super().setUp()
        self.create_table()
        self.addCleanup(self.drop_table)

    def create_table(self):
        management.call_command("createcachetable", verbosity=0)

    def drop_table(self):
        with connection.cursor() as cursor:
            table_name = connection.ops.quote_name("test cache table")
            cursor.execute("DROP TABLE %s" % table_name)

Review comment (bug):
These tests will pass even without your changes applied as these methods are always present they were just the wrong implementations. You could assert against their nature instead and the test doesn't need to be `async`

```suggestion
    def test_async_impl(self):
        if cache.get_many is not BaseCache.get_many:
            self.assertIs(cache.aget_many, aget_many)
        ...
```

Code after:
        with self.assertRaisesMessage(TypeError, msg):
            cache.get_or_set("brian")
        with self.assertRaisesMessage(TypeError, msg):
            cache.get_or_set("brian", version=1)
        self.assertIsNone(cache.get("brian", version=1))
        self.assertEqual(cache.get_or_set("brian", 42, version=1), 42)
        self.assertEqual(cache.get_or_set("brian", 1979, version=2), 1979)
        self.assertIsNone(cache.get("brian", version=3))

    def test_get_or_set_racing(self):
        with mock.patch(
            "%s.%s" % (settings.CACHES["default"]["BACKEND"], "add")
        ) as cache_add:
            # Simulate cache.add() failing to add a value. In that case, the
            # default value should be returned.
            cache_add.return_value = False
            self.assertEqual(cache.get_or_set("key", "default"), "default")

    async def test_get_many_async_uses_specialized_implementation(self):
        if (
            cache.get_many.__func__ is not BaseCache.get_many
            and cache.aget_many.__func__ is BaseCache.aget_many
        ):
            with mock.patch.object(cache, "get_many") as mocked:
                mocked.__func__ = lambda x: x
                await cache.aget_many({})
                mocked.assert_called_once()

    async def test_set_many_async_uses_specialized_implementation(self):
        if (
            cache.set_many.__func__ is not BaseCache.set_many
            and cache.aset_many.__func__ is BaseCache.aset_many
        ):
            with mock.patch.object(cache, "set_many") as mocked:
                mocked.__func__ = lambda x: x
                await cache.aset_many({})
                mocked.assert_called_once()

    async def test_delete_many_async_uses_specialized_implementation(self):
        if (
            cache.delete_many.__func__ is not BaseCache.delete_many
            and cache.adelete_many.__func__ is BaseCache.adelete_many
        ):
            with mock.patch.object(cache, "delete_many") as mocked:
                mocked.__func__ = lambda x: x
                await cache.adelete_many({})
                mocked.assert_called_once()

    async def test_get_or_set_async_uses_specialized_implementation(self):
        await cache.aset("key", "value")
        if (