2016-10-30 2 views
1

Ich versuche, meine Python-Anwendung zu testen, verwenden Sie Unittests mit mock.patch, aber es funktioniert nicht so gut. Mein Code:Python unittest.mock.patch für Funktion funktioniert nicht

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') 

Der Post-Anforderung den Dekorateur aufrufen, die "Benutzer-Auth" get_authenticated_user Funktion überprüfen. Aber im Dekorateur bekam ich Funktion statt Mock-Objekt.

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'} 

Warum in decorators.py ich eine Funktion stattdessen das Mock-Objekt bekam? Python-Version ist 3.4.0

Antwort

3

Sie scheinen den falschen Ort zu patchen. In decorators.py verwenden Sie einen globalen Namen get_authenticated_user(), aber Sie patching einen Namen in api.accounts.helpers stattdessen.

Sie importiert wahrscheinlich get_authenticated_user mit:

from api.accounts.helpers import get_authenticated_user 

was bedeutet, dass die ursprüngliche Lage Patchen wird die Referenz nicht in decorators ändern.

die globale in decorators Patch:

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

Auch die Where to patch section der mock Dokumentation:

patch() Werke (vorübergehend), dass ein Name Punkte mit einem anderen, das Objekt zu ändern. Es kann viele Namen geben, die auf ein einzelnes Objekt verweisen. Um das Patchen zu ermöglichen, müssen Sie sicherstellen, dass Sie den Namen des zu testenden Systems patchen.

Das Grundprinzip ist, dass Sie Patch, wo ein Objekt ist nachgeschlagen, die nicht unbedingt an der gleichen Stelle, wo es definiert ist.

+0

Die 'Import api.accounts.helpers, wie er' in ihrer Testmethode scheint auch ein bisschen seltsam. Zugegeben, es zeigt nicht auf den richtigen Ort zum Patchen, aber wenn es gewesen wäre, hätte es nicht auch Probleme verursacht? – idjaw

+1

@idjaw: das ist nur der OP versucht zu überprüfen, dass der Patch an Ort und Stelle ist. Es ist die falsche Referenz, die jedoch gepatcht wurde. Hätten sie "Decorators importieren" und "decorators.get_authenticated_user" ausprobiert, hätten sie gesehen, dass diese Referenz nicht gepatcht blieb. –

+0

^^ Ja. Das habe ich versucht zu sagen. Vielen Dank. – idjaw

Verwandte Themen