Ich habe verschiedene Artikel über Spott und Stubbing beim Testen gelesen, darunter Martin Fowlers Mocks Aren't Stubs , verstehe aber den Unterschied immer noch nicht.
Ich habe verschiedene Artikel über Spott und Stubbing beim Testen gelesen, darunter Martin Fowlers Mocks Aren't Stubs , verstehe aber den Unterschied immer noch nicht.
Antworten:
Stub
Ich glaube, der größte Unterschied ist, dass ein Stub, den Sie bereits mit vorbestimmtem Verhalten geschrieben haben. Sie hätten also eine Klasse, die die Abhängigkeit (abstrakte Klasse oder Schnittstelle höchstwahrscheinlich) implementiert, die Sie zu Testzwecken vortäuschen, und die Methoden würden nur mit festgelegten Antworten ausgeblendet. Sie würden nichts Besonderes tun und Sie hätten den gestoppelten Code dafür bereits außerhalb Ihres Tests geschrieben.
Spotten
Ein Mock ist etwas, das Sie im Rahmen Ihres Tests mit Ihren Erwartungen einrichten müssen. Ein Mock wird nicht auf eine vorgegebene Weise eingerichtet, sodass Sie Code haben, der dies in Ihrem Test ausführt. Mocks werden in gewisser Weise zur Laufzeit festgelegt, da der Code, der die Erwartungen festlegt, ausgeführt werden muss, bevor sie etwas tun.
Unterschied zwischen Mocks und Stubs
Mit Mocks geschriebene Tests folgen normalerweise einem initialize -> set expectations -> exercise -> verify
Testmuster. Während der vorab geschriebene Stub einem folgen würde initialize -> exercise -> verify
.
Ähnlichkeit zwischen Mocks und Stubs
Der Zweck von beiden besteht darin, das Testen aller Abhängigkeiten einer Klasse oder Funktion zu eliminieren, damit Ihre Tests fokussierter und einfacher in dem sind, was sie zu beweisen versuchen.
Es gibt verschiedene Definitionen von Objekten, die nicht real sind. Der allgemeine Begriff ist Testdoppel . Dieser Begriff umfasst: Dummy , Fake , Stub , Mock .
Nach Martin Fowlers Artikel :
- Dummy- Objekte werden herumgereicht, aber nie benutzt. Normalerweise werden sie nur zum Füllen von Parameterlisten verwendet.
- Gefälschte Objekte haben tatsächlich funktionierende Implementierungen, verwenden jedoch normalerweise eine Verknüpfung, die sie für die Produktion nicht geeignet macht (eine In-Memory-Datenbank ist ein gutes Beispiel).
- Stubs bieten vordefinierte Antworten auf Anrufe, die während des Tests getätigt wurden, und reagieren normalerweise überhaupt nicht auf etwas außerhalb der für den Test programmierten. Stubs können auch Informationen über Anrufe aufzeichnen, z. B. einen E-Mail-Gateway-Stub, der sich an die Nachrichten erinnert, die er "gesendet" hat, oder nur an die Anzahl der Nachrichten, die er "gesendet" hat.
- Mocks sind das, worüber wir hier sprechen: Objekte, die mit Erwartungen vorprogrammiert sind und eine Spezifikation der Anrufe bilden, die sie voraussichtlich erhalten.
Mocks vs Stubs = Verhaltenstests vs Zustandstests
Nach dem Prinzip des Tests kann nur eine Sache pro Test mehrere Stubs in einem Test enthalten, aber im Allgemeinen gibt es nur einen Schein.
Testlebenszyklus mit Stubs:
Testlebenszyklus mit Mocks:
Sowohl Mocks- als auch Stubs-Tests geben eine Antwort auf die Frage: Was ist das Ergebnis?
Tests mit Mocks interessieren sich auch für: Wie wurde das Ergebnis erzielt?
Ein Stub ist ein einfaches falsches Objekt. Es stellt nur sicher, dass der Test reibungslos verläuft.
Ein Mock ist ein schlauerer Stummel. Sie überprüfen, ob Ihr Test erfolgreich ist.
Hier ist eine Beschreibung von jedem, gefolgt von einem Beispiel aus der realen Welt.
Dummy - nur falsche Werte, um die zu befriedigen API
.
Beispiel : Wenn Sie eine Methode einer Klasse testen, für die viele obligatorische Parameter in einem Konstruktor erforderlich sind, die sich nicht auf Ihren Test auswirken , können Sie Dummy-Objekte erstellen, um neue Instanzen einer Klasse zu erstellen.
Fake - Erstellen Sie eine Testimplementierung einer Klasse, die möglicherweise von einer externen Infrastruktur abhängig ist. (Es wird empfohlen, dass Ihr Komponententest NICHT mit der externen Infrastruktur interagiert.)
Beispiel : Erstellen Sie eine gefälschte Implementierung für den Zugriff auf eine Datenbank und ersetzen Sie sie durch eine
in-memory
Sammlung.
Stub - Override-Methoden zur Rückgabe fest codierter Werte, auch als bezeichnet state-based
.
Beispiel : Ihre Testklasse hängt von einer Methode ab
Calculate()
, deren Abschluss 5 Minuten dauert. Anstatt 5 Minuten zu warten, können Sie die eigentliche Implementierung durch einen Stub ersetzen, der fest codierte Werte zurückgibt. nur einen kleinen Bruchteil der Zeit in Anspruch nehmen.
Mock - sehr ähnlich, Stub
aber interaction-based
nicht staatlich. Dies bedeutet, dass Sie nicht erwarten Mock
, einen Wert zurückzugeben, sondern davon ausgehen, dass eine bestimmte Reihenfolge der Methodenaufrufe erfolgt.
Beispiel: Sie testen eine Benutzerregistrierungsklasse. Nach dem Anruf
Save
sollte es anrufenSendConfirmationEmail
.
Stubs
und Mocks
sind eigentlich Untertypen von Mock
, beide tauschen echte Implementierung mit Testimplementierung aus, aber aus unterschiedlichen, spezifischen Gründen.
Im codeschool.com- Kurs Rails Testing for Zombies geben sie diese Definition der Begriffe an:
Stub
Zum Ersetzen einer Methode durch Code, der ein angegebenes Ergebnis zurückgibt.
Spotten
Ein Stub mit der Behauptung, dass die Methode aufgerufen wird.
Wie Sean Copenhaver in seiner Antwort beschrieben hat, besteht der Unterschied darin, dass Verspottungen Erwartungen setzen (dh Aussagen darüber machen, ob oder wie sie angerufen werden).
Stubs bestehen Ihre Tests nicht, Mock kann.
Ich denke, die einfachste und klarere Antwort auf diese Frage gibt Roy Osherove in seinem Buch The art of Unit Testing (Seite 85).
Der einfachste Weg, um festzustellen, dass es sich um einen Stub handelt, besteht darin, festzustellen, dass der Stub den Test niemals nicht bestehen kann. Die Behauptungen, die der Test verwendet, richten sich immer gegen die zu testende Klasse.
Andererseits verwendet der Test ein Scheinobjekt, um zu überprüfen, ob der Test fehlgeschlagen ist oder nicht. [...]
Auch hier ist das Scheinobjekt das Objekt, mit dem wir prüfen, ob der Test fehlgeschlagen ist oder nicht.
Das heißt, wenn Sie Behauptungen gegen die Fälschung aufstellen, bedeutet dies, dass Sie die Fälschung als Schein verwenden. Wenn Sie die Fälschung nur verwenden, um den Test ohne Behauptung darüber durchzuführen, verwenden Sie die Fälschung als Stub.
Lassen Sie mich versuchen, alle obigen Erklärungen zusammenzufassen:
Ein Mock testet nur das Verhalten und stellt sicher, dass bestimmte Methoden aufgerufen werden. Ein Stub ist eine testbare Version (per se) eines bestimmten Objekts.
Was meinst du mit Apple?
Wenn Sie es mit dem Debuggen vergleichen:
Stub ist so, als würde man sicherstellen, dass eine Methode den richtigen Wert zurückgibt
Mock ist so, als würde man tatsächlich in die Methode eintreten und sicherstellen, dass alles im Inneren korrekt ist, bevor der richtige Wert zurückgegeben wird.
Die Verwendung eines mentalen Modells hat mir wirklich geholfen, dies zu verstehen, und nicht alle Erklärungen und Artikel, die nicht ganz "eingedrungen" sind.
Stellen Sie sich vor, Ihr Kind hat eine Glasplatte auf dem Tisch und beginnt damit zu spielen. Jetzt hast du Angst, dass es kaputt geht. Also gibst du ihm stattdessen eine Plastikplatte. Das wäre ein Mock (gleiches Verhalten, gleiche Schnittstelle, "weichere" Implementierung).
Angenommen, Sie haben keinen Plastikersatz, und Sie erklären: "Wenn Sie weiter damit spielen, wird es kaputt gehen!". Das ist ein Stub , Sie haben im Voraus einen vordefinierten Status angegeben.
Ein Dummy wäre die Gabel, die er nicht einmal benutzt hat ... und ein Spion könnte so etwas wie die gleiche Erklärung sein, die Sie bereits benutzt haben und die funktioniert hat.
Ich denke, der wichtigste Unterschied zwischen ihnen sind ihre Absichten.
Lassen Sie mich versuchen, es in WARUM Stummel vs. WARUM Mock zu erklären
Angenommen, ich schreibe Testcode für den öffentlichen Timeline-Controller meines Mac-Twitter-Clients
Hier ist ein Testbeispielcode
twitter_api.stub(:public_timeline).and_return(public_timeline_array)
client_ui.should_receive(:insert_timeline_above).with(public_timeline_array)
controller.refresh_public_timeline
Indem Sie Mock schreiben, ermitteln Sie die Beziehung zur Objektzusammenarbeit, indem Sie überprüfen, ob die Erwartungen erfüllt sind, während Stub nur das Verhalten des Objekts simuliert.
Ich schlage vor, diesen Artikel zu lesen, wenn Sie mehr über Mocks erfahren möchten: http://jmock.org/oopsla2004.pdf
Um ganz klar und praktisch zu sein:
Stub: Eine Klasse oder ein Objekt, das die Methoden der zu fälschenden Klasse / des zu fälschenden Objekts implementiert und immer das zurückgibt, was Sie möchten.
Beispiel in JavaScript:
var Stub = {
method_a: function(param_a, param_b){
return 'This is an static result';
}
}
Mock: Das Gleiche gilt für stub, fügt jedoch eine Logik hinzu, die beim Aufrufen einer Methode "überprüft", sodass Sie sicher sein können, dass eine Implementierung diese Methode aufruft.
Stellen Sie sich als Beispiel vor, dass Sie eine Benutzerregistrierungsklasse testen, wie @mLevan sagt. Nach dem Aufruf von Save sollte SendConfirmationEmail aufgerufen werden.
Ein sehr dummer Code Beispiel:
var Mock = {
calls: {
method_a: 0
}
method_a: function(param_a, param_b){
this.method_a++;
console.log('Mock.method_a its been called!');
}
}
Diese Folie erklärt die Hauptunterschiede sehr gut.
* Aus CSE 403 Lecture 16, University of Washington (Folie erstellt von "Marty Stepp")
siehe Testdoppel:
Stub : Stub ist ein Objekt, das vordefinierte Daten enthält und diese zum Beantworten von Anrufen während Tests verwendet. Beispiel : Ein Objekt, das einige Daten aus der Datenbank abrufen muss, um auf einen Methodenaufruf zu antworten.
Mocks : Mocks sind Objekte, die empfangene Anrufe registrieren. In der Testzusicherung können wir bei Mocks überprüfen, ob alle erwarteten Aktionen ausgeführt wurden. Zum Beispiel : eine Funktion, die den E-Mail-Versanddienst aufruft. Für mehr überprüfen Sie dies einfach .
Eine Fälschung ist ein Oberbegriff, der verwendet werden kann, um entweder einen Stub oder ein Scheinobjekt (handgeschrieben oder auf andere Weise) zu beschreiben, da beide wie das reale Objekt aussehen.
Ob eine Fälschung ein Stub oder ein Mock ist, hängt davon ab, wie sie im aktuellen Test verwendet wird. Wenn es verwendet wird, um eine Interaktion zu überprüfen (gegen die behauptet wird), ist es ein Scheinobjekt. Ansonsten ist es ein Stummel.
Fakes sorgt dafür, dass der Test reibungslos verläuft. Dies bedeutet, dass der Leser Ihres zukünftigen Tests versteht, wie sich das gefälschte Objekt verhält, ohne seinen Quellcode lesen zu müssen (ohne von externen Ressourcen abhängig zu sein).
Was bedeutet reibungsloser Testlauf?
Beispiel im folgenden Code:
public void Analyze(string filename)
{
if(filename.Length<8)
{
try
{
errorService.LogError("long file entered named:" + filename);
}
catch (Exception e)
{
mailService.SendEMail("admin@hotmail.com", "ErrorOnWebService", "someerror");
}
}
}
Sie möchten die mailService.SendEMail () -Methode testen. Dazu müssen Sie eine Ausnahme in Ihrer Testmethode simulieren. Sie müssen also nur eine Fake Stub-errorService-Klasse erstellen, um dieses Ergebnis zu simulieren. Dann kann Ihr Testcode testen mailService.SendEMail () -Methode. Wie Sie sehen, müssen Sie ein Ergebnis simulieren, das aus einer anderen External Dependency ErrorService-Klasse stammt.
Direkt aus dem Papier Mock Roles, nicht Objects , von den Entwicklern von jMock:
Stubs sind Dummy-Implementierungen von Produktionscode, die vordefinierte Ergebnisse zurückgeben. Scheinobjekte fungieren als Stubs, enthalten jedoch auch Behauptungen, um die Interaktionen des Zielobjekts mit seinen Nachbarn zu instrumentieren.
Die Hauptunterschiede sind also:
Um es zusammenzufassen, während auch die Verwirrung zu zerstreuen versucht Fowler Artikel Titel: Mocks sind Stubs, aber sie sind nicht nur Stubs .
Ich las The Art of Unit Testing und stieß auf die folgende Definition:
Eine Fälschung ist ein Oberbegriff, der verwendet werden kann, um entweder einen Stub oder ein Scheinobjekt (handgeschrieben oder auf andere Weise) zu beschreiben, da beide wie das reale Objekt aussehen. Ob eine Fälschung ein Stub oder ein Mock ist, hängt davon ab, wie sie im aktuellen Test verwendet wird. Wenn es verwendet wird, um eine Interaktion zu überprüfen (gegen die behauptet wird), ist es ein Scheinobjekt . Ansonsten ist es ein Stummel .
Ich bin auf diesen interessanten Artikel von UncleBob The Little Mocker gestoßen . Es erklärt die gesamte Terminologie auf sehr leicht verständliche Weise und ist daher für Anfänger nützlich. Der Artikel von Martin Fowlers ist besonders für Anfänger wie mich schwer zu lesen.
Stub hilft uns, den Test durchzuführen. Wie? Es gibt Werte an, die beim Ausführen des Tests helfen. Diese Werte sind selbst nicht real und wir haben diese Werte nur zum Ausführen des Tests erstellt. Zum Beispiel erstellen wir eine HashMap, um uns Werte zu geben, die den Werten in der Datenbanktabelle ähnlich sind. Anstatt direkt mit der Datenbank zu interagieren, interagieren wir mit Hashmap.
Mock ist ein gefälschtes Objekt, das den Test ausführt. wo wir behaupten.
Siehe das folgende Beispiel für Mocks vs Stubs mit C # und Moq Framework. Moq hat kein spezielles Schlüsselwort für Stub, aber Sie können das Mock-Objekt auch zum Erstellen von Stubs verwenden.
namespace UnitTestProject2
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
[TestClass]
public class UnitTest1
{
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method calls Repository GetName method "once" when Id is greater than Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_GetNameCalledOnce()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Once);
}
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method doesn't call Repository GetName method when Id is Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsZero_GetNameNeverCalled()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(0);
// Assert
mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Never);
}
/// <summary>
/// Test using Stub to Verify that GetNameWithPrefix method returns Name with a Prefix
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_ReturnsNameWithPrefix()
{
// Arrange
var stubEntityRepository = new Mock<IEntityRepository>();
stubEntityRepository.Setup(m => m.GetName(It.IsAny<int>()))
.Returns("Stub");
const string EXPECTED_NAME_WITH_PREFIX = "Mr. Stub";
var entity = new EntityClass(stubEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
Assert.AreEqual(EXPECTED_NAME_WITH_PREFIX, name);
}
}
public class EntityClass
{
private IEntityRepository _entityRepository;
public EntityClass(IEntityRepository entityRepository)
{
this._entityRepository = entityRepository;
}
public string Name { get; set; }
public string GetNameWithPrefix(int id)
{
string name = string.Empty;
if (id > 0)
{
name = this._entityRepository.GetName(id);
}
return "Mr. " + name;
}
}
public interface IEntityRepository
{
string GetName(int id);
}
public class EntityRepository:IEntityRepository
{
public string GetName(int id)
{
// Code to connect to DB and get name based on Id
return "NameFromDb";
}
}
}
Sichtweise von Stub- und Mock-Tests:
Stub ist eine Dummy-Implementierung, die vom Benutzer statisch ausgeführt wird, dh wenn Stub den Implementierungscode schreibt. Daher kann die Dienstdefinition und der dynamische Zustand nicht verarbeitet werden. Normalerweise erfolgt dies im JUnit-Framework, ohne das Mocking-Framework zu verwenden.
Mock ist auch eine Dummy-Implementierung, aber die Implementierung erfolgt dynamisch mithilfe von Mocking-Frameworks wie Mockito. So können wir Bedingungs- und Dienstdefinitionen dynamisch behandeln, dh Mocks können zur Laufzeit dynamisch aus Code erstellt werden. Mit Mock können wir Stubs also dynamisch implementieren.
Plus nützliche Antworten, einer der mächtigsten Punkte bei der Verwendung von Mocks als Subs
Wenn der Mitarbeiter [von dem der Hauptcode abhängt] nicht unter unserer Kontrolle steht (z. B. aus einer Bibliothek eines Drittanbieters),
ist Stub in diesem Fall schwieriger zu schreiben als zu verspotten .
Ich habe in meiner Antwort Python-Beispiele verwendet, um die Unterschiede zu veranschaulichen.
Stub - Stubbing ist eine Softwareentwicklungstechnik, mit der Klassenmethoden früh im Entwicklungslebenszyklus implementiert werden. Sie werden üblicherweise als Platzhalter für die Implementierung einer bekannten Schnittstelle verwendet, wobei die Schnittstelle finalisiert oder bekannt ist, die Implementierung jedoch noch nicht bekannt oder finalisiert ist. Sie beginnen mit Stubs, was einfach bedeutet, dass Sie nur die Definition einer Funktion aufschreiben und den eigentlichen Code für später belassen. Der Vorteil ist, dass Sie Methoden nicht vergessen und weiterhin über Ihr Design nachdenken können, während Sie es im Code sehen. Sie können Ihren Stub auch eine statische Antwort zurückgeben lassen, damit die Antwort sofort von anderen Teilen Ihres Codes verwendet werden kann. Stub-Objekte liefern eine gültige Antwort, aber sie sind statisch, unabhängig davon, welche Eingabe Sie übergeben. Sie erhalten immer dieselbe Antwort:
class Foo(object):
def bar1(self):
pass
def bar2(self):
#or ...
raise NotImplementedError
def bar3(self):
#or return dummy data
return "Dummy Data"
Spotten werden in Scheintestfällen verwendet, die bestätigen, dass bestimmte Methoden für diese Objekte aufgerufen werden. Scheinobjekte sind simulierte Objekte, die das Verhalten realer Objekte auf kontrollierte Weise nachahmen. Normalerweise erstellen Sie ein Scheinobjekt, um das Verhalten eines anderen Objekts zu testen. Mit Mocks können wir Ressourcen simulieren, die entweder nicht verfügbar oder für Unit-Tests zu unhandlich sind.
mymodule.py:
import os
import os.path
def rm(filename):
if os.path.isfile(filename):
os.remove(filename)
test.py:
from mymodule import rm
import mock
import unittest
class RmTestCase(unittest.TestCase):
@mock.patch('mymodule.os')
def test_rm(self, mock_os):
rm("any path")
# test that rm called os.remove with the right parameters
mock_os.remove.assert_called_with("any path")
if __name__ == '__main__':
unittest.main()
Dies ist ein sehr einfaches Beispiel, das nur rm ausführt und den Parameter bestätigt, mit dem es aufgerufen wurde. Sie können Mock für Objekte verwenden, nicht nur für die hier gezeigten Funktionen, sondern Sie können auch einen Wert zurückgeben, damit ein Mock-Objekt verwendet werden kann, um einen Stub zum Testen zu ersetzen.
Weitere Informationen zu unittest.mock finden Sie in Python 2.x. Mock ist nicht in unittest enthalten, sondern ein herunterladbares Modul, das über pip heruntergeladen werden kann (pip install mock).
Ich habe auch "The Art of Unit Testing" von Roy Osherove gelesen und ich denke, es wäre großartig, wenn ein ähnliches Buch mit Python- und Python-Beispielen geschrieben würde. Wenn jemand von einem solchen Buch weiß, teilen Sie es bitte. Prost :)
Ein Stub ist ein gefälschtes Objekt, das zu Testzwecken erstellt wurde. Ein Mock ist ein Stub, der aufzeichnet, ob erwartete Anrufe tatsächlich aufgetreten sind.
Ein Stub ist eine leere Funktion, mit der unbehandelte Ausnahmen bei Tests vermieden werden:
function foo(){}
Ein Mock ist eine künstliche Funktion, mit der Betriebssystem-, Umgebungs- oder Hardwareabhängigkeiten während der Tests vermieden werden:
function foo(bar){ window = this; return window.toString(bar); }
In Bezug auf Behauptungen und Zustand:
Verweise
Dort oben gibt es viele gültige Antworten, aber ich denke, es lohnt sich, dieses Formular zu erwähnen: Onkel Bob: https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html
Die beste Erklärung aller Zeiten mit Beispielen!
Ein Mock ist sowohl ein technisches als auch ein funktionales Objekt.
Der Schein ist technisch . Es wird in der Tat von einer Spottbibliothek erstellt (EasyMock, JMockit und in jüngerer Zeit sind Mockito dafür bekannt), dank der Bytecode-Generierung .
Die Scheinimplementierung wird so generiert , dass wir sie instrumentieren können, um beim Aufrufen einer Methode einen bestimmten Wert zurückzugeben, aber auch einige andere Dinge wie die Überprüfung, ob eine Scheinmethode mit bestimmten Parametern aufgerufen wurde (strenge Prüfung) oder welche Parameter auch immer ( keine strenge Kontrolle).
Ein Mock instanziieren:
@Mock Foo fooMock
Verhalten aufzeichnen:
when(fooMock.hello()).thenReturn("hello you!");
Aufruf überprüfen:
verify(fooMock).hello()
Dies ist eindeutig nicht die natürliche Methode, um die Foo-Klasse / das Foo-Verhalten zu instanziieren / zu überschreiben. Deshalb beziehe ich mich auf einen technischen Aspekt.
Aber das Mock ist auch funktional , weil es eine Instanz der Klasse ist , müssen wir von der SUT zu isolieren. Und mit aufgezeichneten Verhaltensweisen könnten wir es im SUT genauso verwenden wie mit einem Stub.
Der Stub ist nur ein funktionales Objekt: Das ist eine Instanz der Klasse, die wir vom SUT isolieren müssen, und das ist alles. Das bedeutet, dass sowohl die Stub-Klasse als auch alle Verhaltens-Fixtures, die während unserer Unit-Tests benötigt werden, explizit definiert werden müssen.
Zum Beispiel hello()
müsste ein Stub die Foo
Klasse in eine Unterklasse unterteilen (oder ihre Schnittstelle implementieren, über die sie verfügt) und Folgendes überschreiben hello()
:
public class HelloStub extends Hello{
public String hello {
return "hello you!";
}
}
Wenn für ein anderes Testszenario eine andere Wertrückgabe erforderlich ist, müssen wir wahrscheinlich eine generische Methode zum Festlegen der Rückgabe definieren:
public class HelloStub extends Hello{
public HelloStub(String helloReturn){
this.helloReturn = helloReturn;
}
public String hello {
return helloReturn;
}
}
Anderes Szenario: Wenn ich eine Nebenwirkungsmethode hätte (keine Rückgabe) und überprüfen würde, ob diese Methode aufgerufen wurde, hätte ich wahrscheinlich einen Booleschen Wert oder einen Zähler in die Stub-Klasse einfügen müssen, um zu zählen, wie oft die Methode aufgerufen wurde.
Fazit
Der Stub benötigt oft viel Overhead / Code, um für Ihren Unit-Test zu schreiben. Was Mock verhindert, dank der sofort einsatzbereiten Aufnahme- / Überprüfungsfunktionen.
Aus diesem Grund wird der Stub-Ansatz heutzutage in der Praxis mit dem Aufkommen hervorragender Scheinbibliotheken selten verwendet.
Über den Artikel von Martin Fowler: Ich denke nicht, dass ich ein "Mockist" -Programmierer bin, während ich Mocks benutze und Stubs vermeide.
Aber ich verwende Mock, wenn es wirklich erforderlich ist (ärgerliche Abhängigkeiten), und ich bevorzuge Test-Slicing- und Mini-Integrationstests, wenn ich eine Klasse mit Abhängigkeiten teste, deren Mocking ein Overhead wäre.