[RUBY] Mock and Stub in RSpec

Verweise Everyday Rails-Einführung in das Testen von Schienen mit RSpec https://leanpub.com/everydayrailsrspec-jp

Mock and Stub

spotten

Ein Objekt, das vorgibt, ein reales Objekt zu sein, das zum Testen verwendet wird. Wird auch als Testdoppel bezeichnet. Der Mock greift nicht auf die Datenbank zu, was die Testzeit verkürzt.

Stummel

Überschreibt die Methoden des Objekts und gibt einen vorgegebenen Wert zurück. Ein Stub ist eine Dummy-Methode, die beim Aufruf ein reales Ergebnis zum Testen zurückgibt. Stubs werden häufig verwendet, um die Standardfunktionalität einer Methode zu überschreiben. Insbesondere wird die Verarbeitung gezielt, die eine Datenbank oder ein Netzwerk verwendet.

Ich werde tatsächlich schreiben

Die Methode name (Kombination aus Vorname + Nachname) im Benutzerobjekt wird an das Notizobjekt delegiert und Attribute werden hinzugefügt.

Benutzerattribute Vorname und Nachname ↓ Kombinieren Sie Vorname und Nachname mit der Methode name des Benutzers ↓ Fügen Sie den kombinierten Wert als Benutzername zum Attribut Note hinzu

Testen Sie, ob dies ordnungsgemäß funktioniert.

Erster Code.rb


it "Delegieren Sie den Namen an den Benutzer, der die Notiz erstellt hat" do
 user = FactoryBot.create(:user, first_name: "Fake", last_name: "User")
 note = Note.new(user: user)
 expect(note.user_name).to eq "Fake User"
end

In diesem Code Das Benutzerobjekt muss in der Datenbank gespeichert und dauerhaft gemacht werden. Mit zunehmender Anzahl und Komplexität schwillt nur die uninteressante Verarbeitung an, obwohl es sich um einen Test des Note-Modells handelt. Und im Note-Modelltest weiß ich zu viel über die Implementierung des Benutzermodells. Dieser Test interessiert nicht daran, dass der Name im Benutzermodell die Attribute Vorname und Nachname hat. Sie müssen lediglich wissen, dass das Benutzermodell den Zeichenfolgennamen zurückgibt.

Auf dieser Grundlage wird ein Refactoring durchgeführt.

Überarbeiteter Code.rb


it "Delegieren Sie den Namen an den Benutzer, der die Notiz erstellt hat" do
 #Benutzerobjekt durch double ersetzen(spotten)
 user = double("user", name: "Fake User")
 note = Note.new
  #note.Ein Stub, der explizit angibt, dass der Benutzer aufgerufen wird
 allow(note).to receive(:user).and_return(user)
 expect(note.user_name).to eq "Fake User"
end

Die Persistenz des Benutzerobjekts wurde durch ein Modell ersetzt. Da das Scheinobjekt eine Methode haben soll, werden Schlüssel und Wert nach dem zweiten Argument angegeben. (Die Methode des Benutzernamens gibt "Fake User" zurück.) Wenn Sie dieses Objekt untersuchen, wird eine Klasse mit dem Namen Double angezeigt. Beachten Sie, dass dieses Modell ein Objekt ist, das nur einen Namen zurückgeben kann. Wenn Sie versuchen, den Vornamen wie unten gezeigt zu testen, wird natürlich eine Fehlermeldung angezeigt, da Sie keinen Wert zurückgeben können.

expect(note.user.first_name).to eq "Fake"

Als nächstes schauen wir uns den Stummel an. Der Stub wird mit allow erstellt. (Verwenden Sie allow (obj) .to receive (: method), wenn das Empfängerobjekt kein Scheinobjekt, sondern ein vorhandenes Objekt ist.) Die Schreibmethode ist unten gezeigt.

#and_Der Rückgabewert der Methode wird durch return angegeben.
allow(obj).to receive(:method).and_return(true)

Der überarbeitete Code fordert uns auf, note.user irgendwo im Test aufzurufen.

allow(note).to receive(:user).and_return(user)

Wenn user.name tatsächlich aufgerufen wird, wird der Wert von note.user_id verwendet, um nach dem entsprechenden Benutzer in der Datenbank zu suchen. Anstatt den gefundenen Benutzer zurückzugeben, wird ein Testbenutzer mit doppeltem Namen zurückgegeben.

Klicken Sie hier für einen sehr leicht verständlichen Artikel Developers.IO https://dev.classmethod.jp/articles/rspec-recipe/ Einführung in RSpec, das verwendet werden kann, Teil 3 "Wie schreibe ich einen Test mit einem Mock, der von Null aus verstanden werden kann?" https://qiita.com/jnchito/items/640f17e124ab263a54dd

Jetzt müssen Sie das Benutzerobjekt nicht mehr in der Datenbank speichern und dauerhaft machen. Und für den Note-Modelltest konnte ich ihn mit minimalem Interesse am Benutzermodell umgestalten. Es gibt jedoch immer noch Probleme.

Test doppelt mit Verifizierungsfunktion

Das Test-Double von RSpec überprüft nicht, ob das Objekt, das ersetzt werden soll, über eine Methode verfügt, die es stubben möchte. Mit anderen Worten, die vom Stub aufgerufene Methode ist undefiniert, aber der Test besteht. Wenn Sie ein Testdoppel so oft wie möglich verwenden, ist es wünschenswert, ein Testdoppel mit einer Verifizierungsfunktion zu verwenden. Wechseln Sie daher zu einem verifizierten Double mit einer Verifizierungsfunktion.

Der Code wurde mit der Bestätigung in "doppelt" geändert.rb


it "Delegieren Sie den Namen an den Benutzer, der die Notiz erstellt hat" do
 #instance_Wechseln Sie zu double. Ändern Sie den ersten Buchstaben des Benutzers in Großbuchstaben
 user = instance_double("User", name: "Fake User")
 note = Note.new
 allow(note).to receive(:user).and_return(user)
 expect(note.user_name).to eq "Fake User"
end

Es ist im Grunde dasselbe wie double, außer dass Sie einen Fehler erhalten, wenn Sie eine undefinierte Instanzmethode stubben. Daher ist es möglich, einen Test zu schreiben und gleichzeitig zu bestätigen, dass die Methode vorhanden ist.

Vielen Dank, dass Sie bis zum Ende bei uns bleiben. Wenn Sie Anregungen oder Ratschläge haben, würde ich mich freuen, wenn Sie einen Kommentar abgeben könnten.

Recommended Posts

Mock and Stub in RSpec
Mock and Stub mit Minitest (RR, WebMock, MiniTest :: Mock verwenden)
[Rails] So definieren Sie Makros in Rspec und standardisieren die Verarbeitung
Verspotten und spionieren Sie PowerMock aus
Verspotten Sie statische Methoden in Mockito 3.4
[Wire Mock] Ich möchte einen Stub / Mock-Server in Java einrichten und E2E-Tests durchführen.
Wenn Sie eine Methode in RSpec verspotten möchten, sollten Sie die Methode allow für mock und die Singleton-Methode verwenden.
Aktivieren Sie jQuery und Bootstrap in Rails 6 (Rails 6).
Beispiel für Codierung und Decodierung in Java
Versuchen Sie, ruby-net-nntp und tmail im Jahr 2020 auszuführen
Grober Unterschied zwischen RSpec und Minitest
CGI in C und Dart: Einführung (1)
StringBuffer- und StringBuilder-Klasse in Java
Schreiben Sie Schlüssel und Werte in Ruby
Entfernen Sie "Assets" und "Turbolinks" in "Rails6".
CRUD-Funktion und MVC in Rails
Verstehe gleich und hashCode in Java
Kopieren Sie den Test und fügen Sie ihn mit RSpec ein
Hallo Welt in Java und Gradle
So testen Sie eine private Methode und verspotten sie teilweise in Java