RSpec - Test Doppel

In diesem Kapitel werden wir RSpec Doubles, auch als RSpec Mocks bekannt, behandeln. Ein Double ist ein Objekt, das für ein anderes Objekt „stehen“ kann. Sie fragen sich wahrscheinlich, was das genau bedeutet und warum Sie eines brauchen würden.

Angenommen, Sie erstellen eine Anwendung für eine Schule und haben eine Klasse, die ein Klassenzimmer für Schüler darstellt, und eine andere Klasse für Schüler, dh Sie haben eine Klassenzimmerklasse und eine Schülerklasse. Sie müssen zuerst den Code für eine der Klassen schreiben. Beginnen wir also mit der Classroom-Klasse -

class ClassRoom 
   def initialize(students) 
      @students = students 
   end 
   
   def list_student_names 
      @students.map(&:name).join(',') 
   end 
end

Dies ist eine einfache Klasse mit einer Methode list_student_names, die eine durch Kommas getrennte Zeichenfolge von Schülernamen zurückgibt. Jetzt möchten wir Tests für diese Klasse erstellen, aber wie machen wir das, wenn wir die Schülerklasse noch nicht erstellt haben? Wir brauchen einen Test Double.

Wenn wir eine "Dummy" -Klasse haben, die sich wie ein Student-Objekt verhält, hängen unsere ClassRoom-Tests nicht von der Student-Klasse ab. Wir nennen dies Testisolation.

Wenn unsere ClassRoom-Tests nicht auf anderen Klassen basieren, können wir bei einem fehlgeschlagenen Test sofort feststellen, dass in unserer ClassRoom-Klasse ein Fehler vorliegt und nicht in einer anderen Klasse. Denken Sie daran, dass Sie in der realen Welt möglicherweise eine Klasse erstellen, die mit einer anderen Klasse interagieren muss, die von einer anderen Person geschrieben wurde.

Hier werden RSpec Doubles (Mocks) nützlich. Unsere Methode list_student_names ruft die Methode name für jedes Student-Objekt in seiner Mitgliedsvariablen @students auf. Daher benötigen wir ein Double, das eine Namensmethode implementiert.

Hier ist der Code für ClassRoom zusammen mit einem RSpec-Beispiel (Test). Beachten Sie jedoch, dass keine Schülerklasse definiert ist.

class ClassRoom 
   def initialize(students) 
      @students = students 
   end
   
   def list_student_names 
      @students.map(&:name).join(',') 
   end 
end

describe ClassRoom do 
   it 'the list_student_names method should work correctly' do 
      student1 = double('student') 
      student2 = double('student') 
      
      allow(student1).to receive(:name) { 'John Smith'} 
      allow(student2).to receive(:name) { 'Jill Smith'} 
      
      cr = ClassRoom.new [student1,student2]
      expect(cr.list_student_names).to eq('John Smith,Jill Smith') 
   end 
end

Wenn der obige Code ausgeführt wird, wird die folgende Ausgabe erzeugt. Die verstrichene Zeit kann auf Ihrem Computer geringfügig abweichen -

. 
Finished in 0.01 seconds (files took 0.11201 seconds to load) 
1 example, 0 failures

Wie Sie sehen können, verwenden Sie a test doubleMit dieser Option können Sie Ihren Code auch dann testen, wenn er auf einer Klasse basiert, die nicht definiert oder nicht verfügbar ist. Dies bedeutet auch, dass Sie bei einem Testfehler sofort feststellen können, dass es sich um ein Problem in Ihrer Klasse handelt und nicht um eine Klasse, die von einer anderen Person geschrieben wurde.