2016-03-10 12 views
14

Wenn Sie eine Funktion mit Mock-Patch, haben Sie die Möglichkeit als Getreu angeben Autospec:Warum ist Autospec bei Verwendung von unittest.mock.patch standardmäßig nicht True?

Wenn Sie Wahr Autospec gesetzt = dann mit dem Modell mit einem spec ersetzt von dem Objekt erzeugt werden wird. Alle Attribute des Mocks werden auch haben die Spezifikation des entsprechenden Attributs des Objekts ersetzt werden. Für Methoden und Funktionen, die verspottet werden, werden die Argumente überprüft und ein TypeError ausgelöst, wenn sie mit der falschen Signatur aufgerufen werden.

(http://www.voidspace.org.uk/python/mock/patch.html)

Ich frage mich, warum dies nicht das Standardverhalten ist? Sicher würden wir fast immer falsche Parameter an irgendeine Funktion, die wir patchen, weitergeben wollen?

Antwort

14

Die einzige klare Art und Weise, dies zu erklären, ist eigentlich die documentation auf dem Nachteil der Verwendung von Auto-speccing zu zitieren und warum sollten Sie vorsichtig sein, wenn es zu benutzen:

Dies ist nicht ohne Einschränkungen und Einschränkungen, weshalb es nicht das Standardverhalten ist. Um zu wissen, welche Attribute für das Spezifikationsobjekt verfügbar sind, muss autospec die Spezifikation prüfen (auf die Attribute zugreifen). Wenn Sie Attribute auf dem Mock durchqueren, findet eine entsprechende Durchquerung des ursprünglichen Objekts unter der Haube statt. Wenn eines Ihrer angegebenen Objekte Eigenschaften oder Deskriptoren hat, die Codeausführung auslösen können, können Sie möglicherweise Autospec nicht verwenden. Auf der anderen Seite ist es viel besser, Ihre Objekte so zu gestalten, dass die Introspektion sicher ist [4].

Ein ernsteres Problem ist, dass es üblich ist, zum Beispiel Attribute im init Methode erstellt werden und nicht an alle auf die Klasse existieren. autospec kann keine dynamisch erzeugten Attribute kennen und schränkt die API auf sichtbare Attribute ein.

Ich denke, der Schlüssel zum Mitnehmen dieser Linie ist hier zu beachten: Autospec kann über alle dynamisch erstellten Attribute nicht, und schränkt die api auf sichtbare Attribute

Also, mit einem Wesen deutlicher zu helfen Beispiel dafür, wo autospeccing Pausen, in diesem Beispiel aus der Dokumentation aufgenommen wurde, zeigt dies:

>>> class Something: 
... def __init__(self): 
...  self.a = 33 
... 
>>> with patch('__main__.Something', autospec=True): 
... thing = Something() 
... thing.a 
... 
Traceback (most recent call last): 
    ... 
AttributeError: Mock object has no attribute 'a' 

Wie Sie sehen können, autospeccing keine Ahnung hat, dass es ein Attribut a erstellt werden, wenn Ihrdie SchaffungObjekt.

Normalerweise für mich selbst, ich spotte nur Patch und Autospec nicht so viel verwenden, da das Verhalten in der Regel im Einklang mit meinen Erwartungen ist.

Es ist nichts falsch daran, Ihrem Instanzattribut einen Wert zuzuweisen.

Beachten Sie die folgenden Funktionsbeispiel:

import unittest 
from mock import patch 

def some_external_thing(): 
    pass 

def something(x): 
    return x 

class MyRealClass: 
    def __init__(self): 
     self.a = some_external_thing() 

    def test_thing(self): 
     return something(self.a) 



class MyTest(unittest.TestCase): 
    def setUp(self): 
     self.my_obj = MyRealClass() 

    @patch('__main__.some_external_thing')  
    @patch('__main__.something') 
    def test_my_things(self, mock_something, mock_some_external_thing): 
     mock_some_external_thing.return_value = "there be dragons" 
     self.my_obj.a = mock_some_external_thing.return_value 
     self.my_obj.test_thing() 

     mock_something.assert_called_once_with("there be dragons") 


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

Also, ich sage nur, für meine Testfall ich sicherstellen möchten, dass die some_external_thing() Methode nicht auf das Verhalten meiner Unittest nicht beeinflusst, also bin ich Zuweisen meines Instanzattributs nur den Mock per mock_some_external_thing.return_value = "there be dragons".

Verwandte Themen