Heim  >  Artikel  >  Backend-Entwicklung  >  Verspottung von Python-Klassen

Verspottung von Python-Klassen

王林
王林Original
2024-08-28 18:32:30381Durchsuche

Mocking Python Classes

In letzter Zeit musste ich Unit-Tests mit Pytest für ein Python-Modul schreiben. Das Modul enthält eine Klasse, in deren Konstruktor andere Klassen initialisiert werden.

Wie üblich habe ich eine Vorrichtung für diese Klasse erstellt, um das Schreiben eines Tests für jede Klassenmethode zu vereinfachen. Zu diesem Zeitpunkt stieß ich auf einige Probleme, als ich versuchte, die verschiedenen im Konstruktor initiierten Klassen zu verspotten. Das Verspotten hat nicht funktioniert und es wurden immer noch Instanzen dieser Klassen erstellt.

Nach einigen Recherchen und der Kombination einiger verschiedener Lösungen, die ich online gefunden habe, möchte ich mitteilen, wie ich es geschafft habe, die Kurse nachzuahmen.

Lösung

Hier ist ein Beispiel der Klasse, die ich zu verspotten versuchte:

class ClassA:
    def __init__(self):
        self.class_b = ClassB()
        self.class_c = ClassC()
        self.count = 0

Wir möchten bei Tests für jedes Feld dieser Klasse einen Wert festlegen. Dieser Wert kann None oder ein Klassenmock sein, aber wir wollen keine Initiationen der Klassen ClassB und ClassC.

In unserem Fall entscheiden wir, dass self.class_b und self.class_c Mocks sein sollten:

@pytest.fixture
def mock_class_b():
    class_b = Mock(spec=ClassB)
    return class_b

@pytest.fixture
def mock_class_c():
    class_c = Mock(spec=ClassC)
    return class_c

Ein Spielplan für diesen Kurs, der unserem Ziel dient, sieht also so aus:

@pytest.fixture
def class_a_mock(mock_class_b, mock_class_c):
    with patch.object(target=ClassA, attribute="__init__", return_value=None) as mock_init:
        class_a = ClassA()
        class_a.class_b = mock_class_b
        class_a.class_c = mock_class_c
        class_b.count = 0
        return class_a

Der wichtige Teil ist die Verwendung der Funktion patch.object, die aus dem Modul unittest.mock in Python stammt. Es wird beim Testen verwendet, um ein Attribut eines bestimmten Objekts vorübergehend durch einen Schein oder einen anderen Wert zu ersetzen.

Argumente

  1. target=ClassA: das Objekt (normalerweise eine Klasse), dessen Attribut wir patchen möchten.
  2. attribute="__init__": der Name des Attributs, das wir patchen möchten.
  3. return_value=None: Ersetzen der __init__-Methode durch eine Funktion, die nichts tut

Auf diese Weise können wir simulierte Variablen in unserem Fixture erstellen.
Lesen Sie mehr über patch.object

Testtipps

Ich habe dieses Tutorial für solche Fälle geschrieben, in denen wir den Code der Klasse A aus irgendeinem Grund nicht ändern können. Ich empfehle jedoch generell, den Code nach Möglichkeit zu ändern, nicht um die Logik zu ändern, sondern um ihn testbarer zu machen .

Hier sind einige Beispiele, wie man Klasse A ändern kann, um sie testbarer zu machen:

Option 1:Übergeben Sie Instanzen der Klassen B und C als Parameter.
Auf diese Weise können wir beim Schreiben des Fixtures Mocks anstelle von Instanzen übergeben.

class ClassA:
    def __init__(self, class_b_instance, class_c_instance):
        self.class_b = class_b_instance
        self.class_c = class_c_instance
        self.count = 0

Option 2: Erstellen Sie eine boolesche Variable, die den Testmodus angibt.
Auf diese Weise können wir entscheiden, welche Felder der Klasse A bei ihrer Initiierung einen Wert erhalten oder nicht.

class ClassA:
    def __init__(self, test_mode=False):
        if not test_mode:
            self.class_b = ClassB()
            self.class_c = ClassC()
        self.count = 0

Option 3:Erstellen Sie Klasseneinleitungen in einer separaten Methode.
Dieser Ansatz gibt uns die Möglichkeit, den Aufruf von set_class_variables im Testmodul zu vermeiden.

class ClassA:
    def __init__(self):
        self.class_b = None
        self.class_c = None
        self.count = None

    def set_class_variables(self):
        self.class_b = ClassB()
        self.class_c = ClassC()
        self.count = 0

Ich hoffe, das hilft! :)

Das obige ist der detaillierte Inhalt vonVerspottung von Python-Klassen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn