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"
.