Django mock patch doesn't work as I expect

python mock patch
python mock property
python patch function
pytest-mock
python mock constructor
python patch class
python patch function in module
python 2.7 mock

Summary : I am doing an experiment to try to create a simple mock to replace redis. What I'm trying to do should be obvious from the code. Short version is, the mock doesn't work - It's still going to redis and creating keys.

tests.py:

from django.test import TestCase
import mock
from redis_mock.simple_redis_mock import redisMockGetRedis, redisMockFlushDB
from account.util import get_redis

class SimpleTest(TestCase):

    def setUp(self):
        redisMockFlushDB()

    @mock.patch("account.util.get_redis", redisMockGetRedis)
    def test_redis(self):
        key = "hello123"
        value = "world123"
        r = get_redis()
        r.set(key, value)
        value2 = r.get(key)
        self.assertEqual(value, value2)

util.py:

import redis

REDIS_HOST = 'localhost'
REDIS_PORT = 6379
REDIS_DEFAULT_DB = 0

def get_redis():
    print "account.util.get_redis"
    return redis.StrictRedis(
        REDIS_HOST, 
        REDIS_PORT, 
        REDIS_DEFAULT_DB
    )

simple_redis_mock.py:

"""
A simple mock for Redis. Just mocks set, get and expire commands.
"""

class SimpleRedisMockDB:
    db = {}

def redisMockFlushDB():
    """
    Helper function to flush the RedisMock db between test runs
    """
    print "redisMockFlushDB"
    SimpleRedisMock.db = {}

class SimpleRedisMock:
    def get(self, key):
        val = None
        try:
            val = SimpleRedisMockDB.db[key]
        except:
            pass
        print "SimpleRedisMock get(" + str(key) + "):" + str(val)
        return val

    def set(self, key, val):
        print "SimpleRedisMock set(" + str(key) + "," + str(val) +")"
        SimpleRedisMockDB.db[key] = val

    def expire(self, key):
        pass


def redisMockGetRedis():
    print "redisMockGetRedis"
    return SimpleRedisMock()

Now, what I expect is that when I run my test, no redis keys are set. Here's what actually happens:

twang$ redis-cli
redis 127.0.0.1:6379> del hello123
(integer) 1
redis 127.0.0.1:6379> exit
twang$ ./manage.py test account
Creating test database for alias 'default'...
redisMockFlushDB
account.util.get_redis
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
Destroying test database for alias 'default'...
twang$ redis-cli
redis 127.0.0.1:6379> get hello123
"world123"

Simple question : Why isn't mock.patch doing what I expect?

The link

http://www.voidspace.org.uk/python/mock/patch.html#where-to-patch

helped me understand better how to go about patching function calls in python.

Python Mock Gotchas, The reason why it doesn't work is explained in the documentation in a section called Where to patch. Now go and read it if you� Django mock patch doesn't work as I expect. Ask Question Asked 6 years, 10 months ago. Active 1 month ago. Viewed 4k times 2. 1. Summary : I am doing an experiment to

Patch only mocks out the object in the location that you have patched it. A quick bit of example code should help explain what is going on.

from mock import Mock, patch
import unittest

from patch_code import anotherfunc, thefunc

print 'Function imported', thefunc

class SomeTest(unittest.TestCase):

    @patch('patch_code.thefunc', Mock())
    def test_method(self):
        anotherfunc()
        print 'Inside test method', thefunc


if __name__ == '__main__':
    unittest.main()

And the code under test is just two functions:

def thefunc():
    pass

def anotherfunc():
    print 'Inside code under test', thefunc

Running that test gives the following output

Function imported <function thefunc at 0xb740e614>
Inside code under test <Mock id='3071597132'>
Inside test method <function thefunc at 0xb740e614>

You can clearly see that the only place that patch has mocked 'thefunc' is in the code under test.

If you want to test the function get_redis without causing any side effects then you should mock out account.util.redis.StrictRedis and assert that it was called with the correct arguments.

If you want to test functions that use get_redis then you should mock out get_redis and, import the function that is using get_redis, and call that function in your test.

Why your mock doesn't work, Why your mock doesn't work Variables in Python are names that refer to values . We'll use the mock.patch function in a with statement. I'm trying to use the python mock library to patch a Celery task that is run when a model is saved in my django app, to see that it's being called correctly. Basically, the task is defined inside myapp.tasks, and is imported at the top of my models.py-file like so: from .tasks import mytask

Instead of importing get_redis, try import util and call util.get_redis().

How mock.patch decorator works in python, This post will explain how mock.patch decorate in general and… name of this callable object doesn't start from capital character, but actually� After a ticket has a patch, it needs to be reviewed by a second set of eyes. After submitting a pull request, update the ticket metadata by setting the flags on the ticket to say “has patch”, “doesn’t need tests”, etc, so others can find it for review. Contributing doesn’t necessarily always mean writing a patch from scratch.

unittest.mock — mock object library — Python 3.8.5 documentation, Additionally, mock provides a patch() decorator that handles patching module of the wrapped object (so attempting to access an attribute that doesn't exist will� See Where to patch section of unittest.mock documentation for more details. Alternatively, you can use a nifty alternative to patch, that is patch.object. patch.object – simpler to get it right. patch.object is dead simple to use – you just import the object whose attribute you want to patch and apply patch.object:

26.4. unittest.mock — mock object library — Python 3.3.7 , Additionally, mock provides a patch() decorator that handles patching module of the wrapped object (so attempting to access an attribute that doesn't exist will� The patch decorator unittest.mock provides a function called patch, which can be used to “mock out” any object from the module you’re testing. It’s commonly used as a decorator on a test method, or even at the class level, where it’s applied to all the test methods of that class.

How to patch in Python?, See how to use patching in Python in your tests. Learn what to do if patching doesn't work whether you should do it often. Unit tests¶. Django comes with a test suite of its own, in the tests directory of the code base. It’s our policy to make sure all tests pass at all times. We appreciate any and all contributions to the test suite!

Comments
  • Possible duplicate of Python mock patch doesn't work as expected for public method
  • This made it "click" for me +1