Unter den vielen Pseudo-Ides, die TDDs umkreisen, gibt es einige Missachtung für Test-Doubles, nicht zuletzt in Bezug auf ihre lächerlichen Namen.
Sie würden sie irgendwie stolz nennen, sonst Mok, Stub, Fake - ein Gefühl, dass wir nichts wirklich verlieren, wenn wir es nicht benutzen. (Im Gegensatz zu "Integrationstests" und "realen Abhängigkeiten").
Sie können jedoch die Sichtweise ändern. Am Ende unterstützt der Mock nicht nur und nicht so sehr die abhängige Komponente, sondern spezifiziert vielmehr das Verhalten der Abhängigkeit. Und die „echte“ Implementierung ist eine bestimmte aktuelle, möglicherweise fehlerhafte Verkörperung unserer stolzen Idee.
In diesem Sinne jedes Mal, wenn wir schreiben
when(mockDependency.method(inputValue)).thenReturn(returnValue)
,
Wir dokumentieren das Verhalten einiger Komponenten.
Daher gibt es mehrere Konsequenzen.
Scheinobjekte sind sowohl im Wortschatz als auch in der Bedeutung eng mit den tatsächlichen Testspezifikationen verbunden. Sowohl das als auch das andere fokussieren uns auf Anforderungen und Szenarien, aber nicht auf Merkmale der aktuellen Implementierung.
Die Tatsache, dass Aussagen über eine Komponente, die bei Verwendung von Frameworks wie Mockito benetzt werden soll, uns etwas ablenkt, ist auf die Clientklassen verteilt, und es ist schwierig, sie im Auge zu behalten. In diesem Sinne sind explizite Vererbungsklassen mit vordefiniertem Verhalten Mocks vom Typ Mockito vorzuziehen, da Sie damit Skripte kapseln und auf einen Blick anzeigen können.
Daher werden jeder OrderProvider-Klasse Skriptklassen ValidOrderProviderStub, ExpiredOrderProviderStub, InvalidOrderIdException_OrderProviderStub, OnlyOnceOrderProvider usw. hinzugefügt, die sich im selben Paket befinden und von allen Tests gleichzeitig verwendet werden können.
Dies schließt Spionageklassen ein, die einfach selbst zu implementieren sind.
Darüber hinaus ist dieser Ansatz schneller auszuführen und funktioniert ohne Reflektion.
Wenn wir den Code lesen, können wir eine Konvention treffen, dass das Vorhandensein von mok die Möglichkeit eines Skripts bestätigt und dessen Fehlen die Existenz eines solchen Skripts verbietet. Wenn wir Clientklassen verbieten, Mockito-Erwartungen zu schreiben, stellt sich bei der Suche nach NullOrderProvider heraus, dass es kein geeignetes Mock gibt, da Null niemals zurückkehrt und es daher keinen Sinn macht, dieses Szenario zu testen.
Wenn mok eine Spezifikation ist, spiegelt mok unsere Pläne für eine Komponente wider und kann und sollte vor der Implementierung geschrieben werden.
Wenn ein Mok eine Spezifikation ist, ist es hierarchisch und spiegelt das Verhalten der Komponente in Abhängigkeit von bestimmten Bedingungen wider.
Somit kann sich unser Moki zu stark vermehren: bedingungsloses Moki, das immer dasselbe zurückgibt, sowie Moki mit internen Bedingungen, wie z. B. forIdOne_returningOne_forIdTwo_ReturningTwo_OrderProvider. Die letzte Aufzählung und Sie müssen nur einen FakeOrderProvider mit dem entsprechenden Verhalten erstellen, der mit der tatsächlichen Implementierung synchronisiert werden soll.
Wenn also ein Mok eine Spezifikation eines bestimmten Verhaltens ist, dann ist die Implementierung einer Komponente nichts anderes, als das Verhalten einer Komponente mit ihren Moks zu synchronisieren.
Und dies ist vielleicht das Hauptargument gegen Mobs - die Notwendigkeit, ihr Verhalten mit der aktuellen realen Implementierung zu synchronisieren, werden wir beim nächsten Mal separat besprechen.