Lariat
Lariat

Reputation: 167

Python unittest.mock.patch for function don't work

I'm trying to test my python application use unittests with mock.patch but it don't work as well. My code:

test_file.py

from unittest.mock import patch

class TestMaterialsUpdate(TestCase):
    def setUp(self):
        self.client = Client()

    @patch('api.accounts.helpers.get_authenticated_user', return_value={'username': 'username'})
    def test_my_castom_method(self):
       import api.accounts.helpers as he
       print(he.get_authenticated_user) # printed mock here
       print(he.get_authenticated_user) # returned {'username': 'username'}

       url = reverse('materials_create')
       # next call get_authenticated_user will be in post request
       self.client.post(url,data=json.dumps({'data': 'data'}), content_type='application/json')

The post request call the decorator that check "user auth" use get_authenticated_user function. But in decorator I got function instead mock-object.

decorators.py

def login_required(func):
    def wrapper(*args, **kwargs):
        print(get_authenticated_user) # printed <function get_authenticated_user at 0x7fec34b62510>
        user = get_authenticated_user(request) # return None instead {'username: 'username'}

Why in decorators.py I got a function instead the mock-object? Python version is 3.4.0

Upvotes: 2

Views: 2405

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1125258

You appear to be patching the wrong location. In decorators.py you are using a global name get_authenticated_user(), but you are patching a name in api.accounts.helpers instead.

You probably imported get_authenticated_user with:

from api.accounts.helpers import get_authenticated_user

which means that patching the original location won't change the reference in decorators.

Patch the global in decorators:

@patch('decorators.get_authenticated_user', return_value={'username': 'username'})

Also see the Where to patch section of the mock documentation:

patch() works by (temporarily) changing the object that a name points to with another one. There can be many names pointing to any individual object, so for patching to work you must ensure that you patch the name used by the system under test.

The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.

Upvotes: 7

Related Questions