it-swarm.com.de

Was ist der Unterschied zwischen einem Schein und einem Stummel?

Ich habe verschiedene Artikel über Spott gegen Stubbing in Tests gelesen, einschließlich Martin Fowlers Mocks sind keine Stubs , verstehen aber den Unterschied immer noch nicht.

749

Stub

Ich glaube, der größte Unterschied ist, dass ein Stummel, den Sie bereits mit vorbestimmtem Verhalten geschrieben haben. Sie hätten also eine Klasse, die die Abhängigkeit implementiert (abstrakte Klasse oder Schnittstelle am wahrscheinlichsten), die Sie zu Testzwecken fälschen, und die Methoden würden nur mit festgelegten Antworten ersetzt. Sie würden nichts Besonderes tun, und Sie hätten den Code für den Stummel außerhalb Ihres Tests bereits geschrieben.

Spotten

Ein Mock ist etwas, das Sie als Teil Ihres Tests mit Ihren Erwartungen einrichten müssen. Ein Mock ist nicht auf eine vorbestimmte Weise eingerichtet, daher haben Sie Code, der es in Ihrem Test ausführt. Mocks in gewisser Weise werden zur Laufzeit bestimmt, da der Code, der die Erwartungen festlegt, ausgeführt werden muss, bevor sie etwas tun.

Unterschied

Mit Mock geschriebene Tests folgen normalerweise einem initialize -> set expectations -> exercise -> verify-Muster zum Testen. Während der vorab geschriebene Stub einem initialize -> exercise -> verify folgen würde. 

Ähnlichkeit

Der Zweck von beiden besteht darin, alle Abhängigkeiten einer Klasse oder Funktion zu testen, so dass Ihre Tests fokussierter und einfacher in dem sind, was sie zu beweisen versuchen.

604
Sean Copenhaver

Vorwort

Es gibt mehrere Definitionen von Objekten, die nicht echt sind. Der allgemeine Begriff lautet test double. Dieser Begriff umfasst: dummy, fake, stub, mock.

Referenz

Nach Martin Fowlers Artikel :

  • Dummy -Objekte werden herumgereicht, aber nie verwendet. Normalerweise werden sie nur zum Ausfüllen von Parameterlisten verwendet.
  • Fake -Objekte verfügen zwar über funktionierende Implementierungen, benötigen jedoch normalerweise eine Abkürzung, wodurch sie nicht für die Produktion geeignet sind (eine Datenbank im Arbeitsspeicher ist ein gutes Beispiel).
  • Stubs bieten Antworten auf Anrufe, die während des Tests gemacht wurden, und antworten in der Regel nicht auf alles, was sich außerhalb des für den Test vorgesehenen Programms befindet. Stubs können auch Informationen zu Anrufen aufzeichnen, z. B. einen E-Mail-Gateway-Stub, der die von ihm gesendeten Nachrichten speichert, oder nur, wie viele Nachrichten er gesendet hat.
  • Mocks sind das, worüber wir hier sprechen: Objekte, die mit Erwartungen vorprogrammiert sind und eine Spezifikation der Anrufe enthalten, die sie erwarten sollen.

Stil

Mocks vs Stubs = Verhaltenstest vs. Zustandstest

Prinzip

Gemäß dem Prinzip von Test nur eine Sache pro Testkann es in einem Test mehrere Stubs geben, aber im Allgemeinen gibt es nur einen Schein.

Lebenszyklus

Testlebenszyklus mit Stubs:

  1. Setup - Bereiten Sie das zu testende Objekt und seine Stubs-Mitarbeiter vor.
  2. Übung - Testen Sie die Funktionalität.
  3. Status überprüfen - Verwenden Sie Asserts, um den Status des Objekts zu überprüfen.
  4. Teardown - Ressourcen bereinigen.

Testlebenszyklus mit Stößen:

  1. Einstellungsdaten - Bereiten Sie das zu testende Objekt vor.
  2. Erwartungen einrichten - Bereiten Sie Erwartungen in einem Modell vor, das vom primären Objekt verwendet wird.
  3. Übung - Testen Sie die Funktionalität.
  4. Erwartungen überprüfen - Stellen Sie sicher, dass im Mock die richtigen Methoden aufgerufen wurden.
  5. Status überprüfen - Verwenden Sie Asserts, um den Status des Objekts zu überprüfen.
  6. Teardown - Ressourcen bereinigen.

Zusammenfassung

Sowohl das Testen als auch das Testen von Stichproben geben eine Antwort auf die Frage: Was ist das Ergebnis?

Das Testen mit Mock interessiert sich auch für: Wie wurde das Ergebnis erzielt?

710
Ryszard Dżegan

Stub ist ein einfaches Objekt. Es sorgt nur dafür, dass der Test reibungslos läuft.
Mock ist schlauer Stub. Sie überprüfen, ob Ihr Test es durchläuft.

261
Arnis Lapsa

Hier ist eine Beschreibung von jedem, gefolgt von einem Beispiel aus der realen Welt.

  • Dummy - nur falsche Werte, um die API zu erfüllen. 

    Beispiel: Wenn Sie eine Methode einer Klasse testen, für die in einem Konstruktor viele obligatorische Parameter erforderlich sind, die keine Auswirkung haben in Ihrem Test, können Sie Dummy-Objekte für den Zweck erstellen Neue Instanzen einer Klasse erstellen.

  • Fake - Erstellen Sie eine Testimplementierung einer Klasse, die von einer externen Infrastruktur abhängig sein kann. (Es ist gute Praxis, dass Ihr GerätetestNICHTtatsächlich mit der externen Infrastruktur interagiert.)

    Beispiel: Erstellen Sie eine gefälschte Implementierung für den Zugriff auf eine Datenbank und ersetzen Sie sie durch in-memory collection.

  • Stub - Überschreiben Sie Methoden, um hartcodierte Werte zurückzugeben, die auch als state-based bezeichnet werden.

    Beispiel: Ihre Testklasse hängt von der Methode Calculate() ab, die 5 Minuten dauert. Anstatt fünf Minuten zu warten, können Sie die eigentliche Implementierung durch einen Stub ersetzen, der hartcodierte Werte zurückgibt. nur einen kleinen Bruchteil der Zeit.

  • Mock - sehr ähnlich zu Stub, aber interaction-based und nicht zustandsbasiert. Dies bedeutet, dass Sie nicht von Mock erwarten, einen Wert zurückzugeben, sondern davon ausgehen, dass eine bestimmte Reihenfolge von Methodenaufrufen ausgeführt wird.

    Beispiel: Sie testen eine Benutzerregistrierungsklasse. Nach dem Aufruf von Save sollte SendConfirmationEmail aufgerufen werden.

Stubs und Mocks sind eigentlich Untertypen von Mock. Beide tauschen die reale Implementierung mit der Testimplementierung aus, jedoch aus unterschiedlichen, spezifischen Gründen.

189
Lev

Im codeschool.com course, 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 Aussage, dass die Methode aufgerufen wird.

Wie Sean Copenhaver in seiner Antwort beschrieben hat, besteht der Unterschied darin, dass Mocks Erwartungen stellen (d. H. Aussagen machen, ob oder wie sie aufgerufen werden).

160
Dillon Kearns

Stubs versagen nicht bei Ihren Tests.

116
mk_

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 zu sagen, dass wir mit einem Stub zu tun haben, ist zu bemerken, dass der Stub den Test niemals bestehen kann. Die Aussagen, die der Test verwendet, sind immer gegen die Klasse im Test.

Auf der anderen Seite verwendet der Test ein Scheinobjekt, um zu überprüfen, ob die Test fehlgeschlagen oder nicht. [...]

Wiederum ist das Scheinobjekt das Objekt, mit dem wir prüfen, ob der Test fehlgeschlagen ist oder nicht.

Das heißt, wenn Sie Aussagen gegen die Fälschung machen, bedeutet dies, dass Sie die Fälschung als Schein verwenden, wenn Sie die Fälschung nur verwenden, um den Test ohne Behauptung auszuführen, verwenden Sie die Fälschung als Stub.

27
Ghini Antonio

Wenn ich alle obigen Erklärungen lese, möchte ich versuchen, zu verdichten:

  • Stub : ein Dummy-Code, mit dem der Test ausgeführt werden kann, aber es ist Ihnen egal, was damit passiert.
  • Mock : Ein Dummy-Code, den Sie verifizieren, wird im Test richtig aufgerufen.
  • Spy : Ein Dummy-Code, der einige Aufrufe eines echten Codes abfängt, sodass Sie Anrufe überprüfen können, ohne das gesamte Originalobjekt zu ersetzen.
19
O'Rooney

Ein Mock testet lediglich das Verhalten und stellt sicher, dass bestimmte Methoden aufgerufen werden .. _ Ein Stub ist eine überprüfbare Version (an sich) eines bestimmten Objekts.

Was meinst du mit Apple?

18
NebulaFox

Ich denke, der wichtigste Unterschied zwischen ihnen ist ihre Absicht.

Lassen Sie mich versuchen, es in WARUM Stub vs. WARUM Spott zu erklären

Angenommen, ich schreibe Testcode für den öffentlichen Timeline-Controller meines Mac Twitter-Clients

Hier ist ein Beispielcode

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
  • STUB: Die Netzwerkverbindung zur Twitter API ist sehr langsam, was meinen Test langsam macht. Ich weiß, dass es Zeitleisten zurückgeben wird, also habe ich einen Stub erstellt, der die HTTP Twitter API simuliert, sodass mein Test ihn sehr schnell ausführt und ich den Test ausführen kann, selbst wenn ich offline bin. 
  • MOCK: Ich habe bisher noch keine meiner UI-Methoden geschrieben und weiß nicht, welche Methoden ich für mein UI-Objekt schreiben muss. Ich hoffe zu wissen, wie mein Controller mit meinem UI-Objekt zusammenarbeitet, indem ich den Testcode schreibe.

Durch das Schreiben von Mock entdecken Sie die Kollaboration der Objekte, indem Sie überprüfen, ob die Erwartung erfüllt ist, während Stub nur das Verhalten des Objekts simuliert.

Ich schlage vor, diesen Artikel zu lesen, wenn Sie mehr über Mocks wissen wollen: http://jmock.org/oopsla2004.pdf

17
Joe Yang

Wenn Sie es mit dem Debuggen vergleichen:

Stub ist so, als würde man sicherstellen, dass eine Methode den korrekten Wert zurückgibt

Mock ist wie eigentlich in die Methode einsteigen und sicherstellen, dass alles im Inneren korrekt ist, bevor der korrekte Wert zurückgegeben wird.

14
happygilmore

Um ganz klar und praktisch zu sein:

Stub: Eine Klasse oder ein Objekt, das die Methoden der Klasse/des Objekts, die gefälscht werden sollen, 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: Dasselbe wie Stub, fügt jedoch eine Logik hinzu, die den Aufruf einer Methode "überprüft", sodass Sie sicher sein können, dass eine Implementierung diese Methode aufruft. 

Wie @mLevan sagt, stellen Sie sich als Beispiel vor, Sie testen eine Benutzerregistrierungsklasse. 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!');
   }
}
13
R01010010

Diese Folie erklärt die Hauptunterschiede sehr gut.

 enter image description here

* Aus CSE 403, Vortrag 16, University of Washington (von Marty Stepp erstellte Folie)

11

Die Verwendung eines mentalen Modells hat mir wirklich geholfen, dies zu verstehen, und nicht alle Erklärungen und Artikel, die nicht ganz "hineingefallen" sind.

Stellen Sie sich vor, Ihr Kind hat eine Glasplatte auf dem Tisch und beginnt damit zu spielen. Jetzt haben Sie 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, so dass Sie erklären: "Wenn Sie weiter damit spielen, wird es kaputt gehen!". Das ist ein Stub , Sie haben im Voraus einen vordefinierten Zustand angegeben.

A Dummy wäre die Gabel, die er nicht einmal benutzt hat ... und ein Spy könnte so etwas wie die Erklärung geben, die Sie bereits verwendet haben. A Fake wäre wie ein Lügner, dass ein Polizist kommen würde, wenn er fortfährt (nicht sicher über den letzten Teil :).

10
Moshisho

Ich mag die Erklärung von Roy Osherove [Videolink] .

Jede erstellte Klasse oder jedes Objekt ist eine Fälschung. Es ist ein Mock, wenn Sie bestätigen ruft dagegen an. Ansonsten ist es ein Stummel.

10
nitishagar

Ein fake ist ein Oberbegriff, der entweder zur Beschreibung eines Stub Oder eines Scheinobjekts (handgeschrieben oder anderweitig) verwendet werden kann, da beide wie das Real-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 prüfen (gegen die behauptet wird), ist es ein Scheinobjekt. Ansonsten ist es ein Stub.

Fakes stellt sicher, dass der Test reibungslos verläuft. Dies bedeutet, dass der Leser Ihres zukünftigen Tests das Verhalten des gefälschten Objekts verstehen wird, ohne seinen Quellcode lesen zu müssen (ohne auf externe Ressourcen angewiesen zu sein) .

Was bedeutet Testlauf reibungslos?
Forexample im Code unten:

 public void Analyze(string filename)
        {
            if(filename.Length<8)
            {
                try
                {
                    errorService.LogError("long file entered named:" + filename);
                }
                catch (Exception e)
                {
                    mailService.SendEMail("[email protected]", "ErrorOnWebService", "someerror");
                }
            }
        }

Sie möchten die mailService.SendEMail () -Methode testen. Dazu müssen Sie eine Ausnahme in Ihrer Testmethode simulieren. Sie müssen lediglich eine Fake Stub-Klasse errorService erstellen, um dieses Ergebnis zu simulieren. Anschließend wird Ihr Testcode angezeigt können Sie die mailService.SendEMail () -Methode testen. Wie Sie sehen, müssen Sie ein Ergebnis simulieren, das von einer anderen External Dependency ErrorService-Klasse stammt. 

8
Mustafa Ekici
  • Stubs vs. Mocks
    • Stubs
      1. geben Sie spezifische Antworten für Methodenaufrufe an
        • beispiel: myStubbedService.getValues ​​() gibt nur einen String zurück, der vom getesteten Code benötigt wird
      2. wird vom zu testenden Code verwendet, um ihn zu isolieren
      3. test kann nicht fehlschlagen
        • beispiel: myStubbedService.getValues ​​() gibt nur den übergebenen Wert zurück
      4. implementieren oft abstrakte Methoden
    • Mocks
      1. "Superset" von Stubs; kann behaupten, dass bestimmte Methoden als .__ bezeichnet werden.
        • beispiel: Vergewissern Sie sich, dass myMockedService.getValues ​​() nur einmal aufgerufen wird
      2. wird verwendet, um das Verhalten des getesteten Codes zu testen
      3. test kann nicht bestanden werden
        • beispiel: Vergewissern Sie sich, dass myMockedService.getValues ​​() einmal aufgerufen wurde. Die Überprüfung schlägt fehl, da myMockedService.getValues ​​() nicht von meinem getesteten Code aufgerufen wurde
      4. spottet oft Schnittstellen
7
Relu Mesaros

lassen Sie sich die Test-Doubles ansehen:

  • Fake: Fakes sind Objekte mit funktionierenden Implementierungen, die jedoch nicht mit denen der Produktion identisch sind. Wie: Implementierung eines Datenzugriffsobjekts oder eines Repository im Arbeitsspeicher. 
  • Stub: Stub ist ein Objekt, das vordefinierte Daten enthält und es verwendet, um Aufrufe während des Tests zu beantworten. Wie: Ein Objekt, das einige Daten aus der Datenbank abrufen muss, um auf einen Methodenaufruf zu antworten. 

  • Mocks: Mocks sind Objekte, die Anrufe registrieren, die sie empfangen. In Testassertion können wir bei Mocks überprüfen, dass alle erwarteten Aktionen ausgeführt wurden. Wie: Eine Funktion, die den E-Mail-Sendedienst aufruft . Weitere Informationen finden Sie unter this .

Rechts von der Zeitung Scheinrollen, nicht Objekte , von den Entwicklern von jMock:

Stubs sind Scheinimplementierungen des Produktionscodes, die zurückgegebene Werte zurückgeben Ergebnisse. Scheinobjekte dienen als Stubs, enthalten jedoch auch Zusicherungen für instrumentieren Sie die Interaktionen des Zielobjekts mit seinen Nachbarn.

Die Hauptunterschiede sind also:

  • erwartungen, die an Stubs gestellt werden, sind gewöhnlich allgemein, während Erwartungen, die an Mocks gestellt werden, "schlauer" sein können (z. B. dies beim ersten Anruf, beim zweiten Anruf usw. zurückgeben).
  • stubs werden hauptsächlich verwendet, um indirekte Eingänge des SUT einzurichten, während mocks zum Testen von sowohl indirekter Eingänge als auch indirekter Ausgänge des SUT verwendet werden kann.

Zusammenfassend, während auch versucht wird, die Verwirrung aus Fowlers Artikel title zu zerstreuen: Mocks sind Stubs, aber sie sind nicht nur Stubs.

6
Dimos

Ich bin auf diesen interessanten Artikel von UncleBob The Little Mocker gestoßen. Es erklärt die gesamte Terminologie auf eine sehr einfache Art und Weise, so dass es für Anfänger nützlich ist. Martin Fowlers Artikel ist besonders für Anfänger wie mich ein hartes Buch.

3
A.I

Im Folgenden finden Sie ein 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";
        }
    }
}
3
Adarsh Shah

Stub- und Mock-Testperspektive:

  • Stub ist eine Dummy-Implementierung, die vom Benutzer in statisch way gemeint ist, d. H. In Stub den Implementierungscode schreiben. Es kann also keine Dienstdefinition und dynamische Bedingungen verarbeiten. Normalerweise wird dies im JUnit-Framework ohne Mocking-Framework ausgeführt. 

  • Mock ist auch eine Dummy-Implementierung, aber die Implementierung wurde dynamisch mithilfe von Mocking-Frameworks wie Mockito durchgeführt. Daher können wir Bedingung und Service-Definition als dynamische Methode behandeln, d. H. Mocks können zur Laufzeit dynamisch aus Code erstellt werden. So können wir mit Mock Stubs dynamisch implementieren.

3
Premraj

Stub hilft uns, test auszuführen. Wie? Es gibt Werte, die beim Ausführen des Tests hilfreich sind. Diese Werte sind an sich nicht echt und wir haben diese Werte nur erstellt, um den Test durchzuführen. Beispielsweise erstellen wir eine HashMap, um Werte zu erhalten, die den Werten in der Datenbanktabelle ähneln. 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 setzen.

2
user965884

Mockito Beispiel

 enter image description here

Stub gibt nur gespeicherte Daten zurück. Stubs sind einfach und unkompliziert - sie stellen im Wesentlichen die einfachste Implementierung einer Methode dar und geben jedes Mal dieselben gespeicherten Daten zurück. Dies gibt uns die volle Kontrolle über zurückgegebene Werte von Methoden, die von der Abhängigkeit aufgerufen wurden.

Mit Mock object können Sie überprüfen, ob das zu testende Objekt bestimmte Methoden aufgerufen hat.

Und wie Martin Fowler in seinem Aufsatz sagte

Es besteht ein Unterschied darin, dass die stub die Statusüberprüfung verwendet, während die mock die Verhaltensüberprüfung verwendet.

Lesen Sie mehr hier und hier

2
yoAlex5

Ein Stub ist eine leere Funktion, mit der unbehandelte Ausnahmen bei Tests vermieden werden:

function foo(){}

Ein Mock ist eine künstliche Funktion, die verwendet wird, um Abhängigkeiten zwischen Betriebssystem, Umgebung oder Hardware während des Tests zu vermeiden:

function foo(bar){ window = this; return window.toString(bar); }

In Bezug auf Behauptungen und Zustand:

  • Mocks werden vor einer Ereignis- oder Statusänderung geltend gemacht
  • Stubs werden nicht aktiviert, sie geben den Status vor einem Ereignis an, um die Ausführung von Code von nicht verbundenen Einheiten zu vermeiden
  • Spione werden wie Stubs eingerichtet und nach einer Ereignis- oder Zustandsänderung aktiviert
  • Fälschungen werden nicht bestätigt, sie werden nach einem Ereignis mit fest codierten Abhängigkeiten ausgeführt, um Status zu vermeiden

Verweise

2
Paul Sweatte

viele gültige Antworten dort oben, aber ich denke, es lohnt sich, diese Form von Onkel Bob zu erwähnen: https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html

die beste Erklärung, die es je gegeben hat!

2
Kasper

Ich habe in meiner Antwort Python-Beispiele verwendet, um die Unterschiede zu veranschaulichen.

Stub - Stubbing ist eine Softwareentwicklungsmethode, mit der Klassenmethoden früh im Entwicklungszyklus implementiert werden. Sie werden häufig als Platzhalter für die Implementierung einer bekannten Schnittstelle verwendet, wobei die Schnittstelle abgeschlossen oder bekannt ist, die Implementierung jedoch noch nicht bekannt oder abgeschlossen ist. Sie beginnen mit Stubs, was einfach bedeutet, dass Sie nur die Definition einer Funktion aufschreiben und den eigentlichen Code für später aufheben. Der Vorteil ist, dass Sie die Methoden nicht vergessen und Sie können weiterhin über Ihr Design nachdenken, während Sie es im Code sehen. Ihr Stub kann auch eine statische Antwort zurückgeben, sodass die Antwort sofort von anderen Teilen Ihres Codes verwendet werden kann. Stub-Objekte liefern eine gültige Antwort, aber es ist statisch, egal welche Eingabe Sie eingeben, 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"

Mock -Objekte werden in Mock-Testfällen verwendet, um zu bestätigen, dass bestimmte Methoden für diese Objekte aufgerufen werden. Scheinobjekte sind simulierte Objekte, die das Verhalten realer Objekte auf kontrollierte Weise nachahmen. Sie erstellen normalerweise ein Scheinobjekt, um das Verhalten eines anderen Objekts zu testen. Mit Mock können wir Ressourcen simulieren, die für Komponententests entweder nicht verfügbar oder 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 __== '__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 mit Objekten verwenden, nicht nur mit den hier gezeigten Funktionen. Sie können auch einen Wert zurückgeben, sodass ein Mock-Objekt zum Austauschen eines Stubs zum Testen verwendet werden kann.

Weitere Informationen zu unittest.mock , Hinweis in Python 2.x Mock ist nicht in unittest enthalten, es ist jedoch ein herunterladbares Modul, das über pip (pip install mock) heruntergeladen werden kann.

Ich habe auch "The Art of Unit Testing" von Roy Osherove gelesen und finde es toll, wenn ein ähnliches Buch mit Python- und Python-Beispielen geschrieben würde. Wenn jemand ein solches Buch kennt, teilen Sie es bitte mit. Prost :)

2
radtek

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.

2
simon.denel

Ein Proband führt als Reaktion auf bestimmte Aufforderungen (Funktionsaufrufe) oder andere Reize Aktionen aus. Hier sind konkrete Beispiele für Testsituationen.

Szenario - EMT Schülerprüfung

Ein Student hat eine Ausbildung als Rettungssanitäter absolviert. Schauen Sie sich Ian Gallagher in Shameless Season 6, Episode 10 an, wenn Sie mit dieser Testsituation nicht vertraut sind.

Patienten mit verschiedenen Erkrankungen zu Testzwecken zu finden, ist zu teuer. Stattdessen verwenden wir Schauspieler. Wir fragen den Probanden (Ian) "Sie kommen am Tatort an und der Patient ist unbeweglich und bewusstlos, was machen Sie zuerst?" Ian antwortet "Ich überprüfe, ob die Szene sicher ist". Und der Testlehrer sagt "die Szene ist sicher".

Der Ausbilder (und der Schauspieler) können willkürliche Antworten auf die Fragen der Testperson eingeben.

Hier sind der Ausbilder (und der Schauspieler) ein Spott. Das medizinische Training verwendet diese Terminologie (z. B. Scheincodesimulation) genauso wie Informatiker.

Szenario - Registrieren Sie sich für eine Website

Sie testen Yahoo, einen neuen E-Mail-Dienst, von dem Sie gehört haben. Um sich anzumelden, müssen Sie Ihren Geburtstag und Antworten auf andere aufdringliche Fragen angeben.

Die Website erfordert, dass Sie 21 Jahre oder älter sind. Sie geben also den Wert vom 1. Januar 1970 ein. Er erfüllt die Anforderungen und erspart Ihnen den mühsamen Prozess der Implementierung eines Arbeitsablaufs zum Erinnern an meinen Geburtstag und Typ.

Dieses Datum ist ein Stub. Diese Wortverwendung ist spezifisch für die Informatik.

1

A Stub ist ein Objekt, das eine Schnittstelle einer Komponente implementiert. Anstatt jedoch zurückzugeben, was die Komponente beim Aufruf zurückgeben würde, kann der Stub so konfiguriert werden, dass er einen Wert zurückgibt, der für den Test geeignet ist. Mit Stubs kann ein Unit-Test testen, ob eine Unit verschiedene Rückgabewerte ihres Mitbearbeiters verarbeiten kann. Die Verwendung eines Stubs anstelle eines echten Mitarbeiters in einem Komponententest könnte folgendermaßen ausgedrückt werden:

gerätetest -> Stich

gerätetest -> Einheit -> Stich

der Einheitentest legt die Ergebnisse und den Zustand der Einheit fest

Zuerst erstellt der Komponententest den Stub und konfiguriert seine Rückgabewerte. Dann erstellt der Gerätetest die Einheit und setzt den Stub darauf. Nun ruft der Gerätetest das Gerät auf, das wiederum den Stub aufruft. Schließlich gibt der Komponententest Aussagen über die Ergebnisse der Methodenaufrufe des Geräts ab.

A Mockist wie ein Stub, nur er hat Methoden, mit denen bestimmt werden kann, welche Methoden im Mock aufgerufen wurden. Mit einem Mock kann somit sowohl geprüft werden, ob das Gerät verschiedene Rückgabewerte korrekt verarbeiten kann, als auch, ob das Gerät den Mitarbeiter korrekt verwendet. Beispielsweise können Sie anhand des von einem Dao-Objekt zurückgegebenen Werts nicht sehen, ob die Daten mithilfe einer Anweisung oder eines PreparedStatement aus der Datenbank gelesen wurden. Sie können auch nicht sehen, ob die Methode connection.close () aufgerufen wurde, bevor Sie den Wert zurückgeben. Dies ist mit Mock möglich. Mit anderen Worten: Mocks machen es möglich, die komplette Interaktion einer Einheit mit einem Kollaborateur zu testen. Nicht nur die Collaborator-Methoden, die von der Unit verwendete Werte zurückgeben. Die Verwendung eines Mock in einem Unit-Test könnte folgendermaßen ausgedrückt werden:

gerätetest -> Schein

gerätetest -> Einheit -> Spott

der Einheitentest gibt das Ergebnis und den Zustand der Einheit an

unit-Test behauptet die auf Mock genannten Methoden

Mehr Detail >> Hier

1
M_ Fa

Stubs werden für Methoden mit einem erwarteten Rückgabewert verwendet, den Sie in Ihrem Test festgelegt haben .__ Mocks werden für void-Methoden verwendet, die in der Assert verifiziert werden, dass sie aufgerufen werden.

0
Elisabeth

Mock - Ein Mock fängt einen Aufruf einer Methode oder Funktion (oder einer Gruppe von Methoden und Funktionen wie bei einer Mocked-Klasse) ab. Es ist keine Alternative zu dieser Methode oder Funktion. In diesem Abhören kann der Mock alles tun, was er will, z. B. Eingabe und Ausgabe aufzeichnen, den Anruf kurzschließen, den zurückgegebenen Wert ändern usw.

Stub - Ein Stub ist eine gültige voll funktionsfähige Implementierung einer Methode oder Funktion (oder einer Gruppe von Methoden und Funktionen wie bei einer Stubbed-Klasse), die eine identische Schnittstelle/Signatur wie die Methode, Funktion oder Gruppe von hat Methoden und Funktionen, für die es gedämpft wird. Die Stubbed-Implementierung führt im Allgemeinen nur Dinge aus, die im Rahmen eines Komponententests akzeptabel sind. Dies bedeutet, dass sie zum Beispiel IO nicht tut, während sie das Verhalten des Stubbing nachahmt.

0
Didier A.

Ich habe "The Art of Unit Testing" gelesen und bin auf die folgende Definition gestoßen:

Ein Fälschung ist ein allgemeiner Begriff, der entweder zur Beschreibung eines Stubs oder eines Scheinobjekts (handschriftlich oder anderweitig) verwendet werden kann, da beide wie das aussehen echtes Objekt. Ob eine Fälschung ein Stummel oder ein Schein 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 stub.

0
Afonso Matos

Angenommen, Sie haben eine Klasse namens EmployeeService, die Sie testen möchten, und die eine Abhängigkeit von einer Schnittstelle namens EmployeeDao hat:

public class EmployeeService{
   private EmployeeDao dao;
   public EmployeeService(Dao dao){this.dao = dao;}

   public String getEmployeeName(int id){
     Employee emp = bar.goToDatabaseAndBringTheEmployeeWithId(id);
     return emp != null?emp.getFullName:null;
   }
   //Further state and behavior
}

public interface EmployeeDao{
  Employee goToDatabaseAndBringTheEmployeeWithId(int id);
}

In Ihrer Testklasse:

public class EmployeeServiceTest{
   EmployeeService service;
   EmployeeDao mockDao = Mockito.mock(EmployeeDao.class);//Line 3

   @Before
   public void setUp(){
     service = new EmployeeService(mockDao);
   }
   //Tests
   //....
}

In der obigen Testklasse in Zeile 3 sagen wir zum Verspottungs-Framework (in diesem Fall Mockito) "Hey, Mockito, stelle mir ein Objekt her, das die EmployeeDao-Funktionalität hat." Das Framework erstellt ein Objekt mit der Methode goToDatabaseAndBringTheEmployeeWithId, jedoch ohne Textkörper. Es ist Ihre Aufgabe, diesen Spott anzuweisen, was zu tun ist. Das ist ein Schein.

Sie können jedoch auch eine Klasse erstellen, die die EmployeeDao-Schnittstelle implementiert, und diese stattdessen in der Testklasse verwenden:

public EmployeeDaoStub implements EmployeeDao{
   public Employee goToDatabaseAndBringTheEmployeeWithId(int id){
      //No trip to DB, just returning a dummy Employee object
      return new Employee("John","Woo","123 Lincoln str");
   }
}

Verwenden Sie in Ihrer Testklasse diesmal Stub anstelle eines Mocks:

public class EmployeeServiceTest{
   EmployeeService service;
   EmployeeDao daoStub = new EmployeeDaoStub();//Line 3

   @Before
   public void setUp(){
     service = new EmployeeService(daoStub);
   }
   //Tests
   //....
}

Alles in allem sind Stubs die Klassen, die Sie speziell erstellen (oder von jemand anderem erstellt werden), um Abhängigkeiten zu imitieren, nur um den gewünschten Zustand zu erreichen. Ja, wie alle anderen Leute behaupten, handelt es sich meistens um einen Staat. Während Mocks in der Regel durch ein spöttisches Framework erstellt werden und Sie keine Ahnung haben, wie seine Eingeweide aussehen. Aber mit Stubs wissen Sie, welche Klasse Sie bekommen werden: Es ist die, die Sie erstellt haben.

Übrigens, wenn Ihre Abhängigkeit eher eine Klasse als eine Schnittstelle ist, können Sie diese Klasse einfach erweitern, um Ihren Stub zu erstellen.

0

Sowohl Stubs als auch Mocks überschreiben externe Abhängigkeiten, der Unterschied ist jedoch

Stubs -> Daten testen

Mocks -> Verhalten testen


Fake/Dummy -> Teste nichts (überschreibe einfach die Funktionalität mit leeren Methoden, zB ersetze Logger, um während des Testens jegliches Protokollrauschen zu vermeiden)

0
Developer

folgendes ist mein Verständnis ...

  • wenn Sie Testobjekte lokal erstellen und Ihren lokalen Service damit füttern, verwenden Sie ein Scheinobjekt. Dies gibt einen Test für die Methode, die Sie in Ihrem lokalen Dienst implementiert haben. Sie wird zum Überprüfen des Verhaltens verwendet

  • wenn Sie die Testdaten vom realen Diensteanbieter erhalten, jedoch von einer Testversion der Schnittstelle und einer Testversion des Objekts, arbeiten Sie mit Stubs Der Stub kann über Logik verfügen, um bestimmte Eingaben zu akzeptieren und entsprechende Ausgaben zu geben Hilfe bei der Statusüberprüfung ...

0
Andy Lin

Ein Mock ist sowohl ein technisches als auch ein funktionales Objekt.

Das Mock ist technisch. Es wird in der Tat von einer Verspottungsbibliothek (EasyMock, JMockit und in jüngerer Zeit Mockito sind für diese bekannt) dank Byte-Code-Generierung erstellt.
Die Mock-Implementierung ist generiert in einer Art und Weise, in der wir instrument einen bestimmten Wert zurückgeben könnten, wenn eine Methode aufgerufen wird, aber auch einige andere Dinge wie das Überprüfen dass eine Scheinmethode mit bestimmten Parametern (strenge Prüfung) oder mit beliebigen Parametern (keine strenge Prüfung) aufgerufen wurde.

Instanziieren eines Mocks:

@Mock Foo fooMock

Verhalten aufzeichnen:

when(fooMock.hello()).thenReturn("hello you!");

Aufruf überprüfen:

verify(fooMock).hello()

Dies ist eindeutig nicht die natürliche Art, 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, die wir vom SUT isolieren müssen. Und mit aufgezeichneten Verhaltensweisen könnten wir es im SUT genauso verwenden, wie wir es mit einem Stub tun würden.


Der Stub ist nur ein funktionales Objekt: Dies 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 Stoppen von hello() müsste beispielsweise die Klasse Foo in eine Unterklasse unterteilt werden (oder die von ihr verwendete Schnittstelle implementiert werden) und hello() überschrieben werden:

public class HelloStub extends Hello{    
  public String hello { 
      return "hello you!"; 
  }
}

Wenn ein anderes Testszenario eine andere Wertrückgabe erfordert, 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 prüfen würde, ob diese Methode aufgerufen wurde, hätte ich der Stub-Klasse wahrscheinlich einen Booleschen Wert oder einen Zähler hinzufügen müssen, um zu zählen, wie oft die Methode aufgerufen wurde.


Fazit

Der Stub erfordert oft viel Overhead/Code, um für Ihren Unit-Test zu schreiben. Was Mock verhindert, dank sofort einsatzbereiter Aufzeichnungs-/Überprüfungsfunktionen.
Aus diesem Grund wird der Stub-Ansatz heutzutage in der Praxis mit dem Aufkommen ausgezeichneter Scheinbibliotheken selten verwendet.


Über den Martin Fowler-Artikel: Ich glaube nicht, dass ich ein "spöttischer" Programmierer bin, wenn ich spöttische Methoden verwende und Stubs vermeide.
Aber ich benutze Mock, wenn es wirklich erforderlich ist (nervige Abhängigkeiten), und ich bevorzuge Test-Slicing- und Mini-Integrationstests, wenn ich eine Klasse mit Abhängigkeiten teste, bei denen Mocking ein Overhead wäre.

0
davidxxx