2013-02-19 7 views
10

Ich habe eine Funktion, die einen Block akzeptiert, öffnet eine Datei, die Erträge und Renditen:Wie eine Funktion zu testen, die einen Block mit rspec nimmt

def start &block 
    .....do some stuff 
    File.open("filename", "w") do |f| 
     f.write("something") 
     ....do some more stuff 
     yield 
    end 
end 

Ich versuche, einen Test zu schreiben, für die es rspec mit . Wie stosse ich File.open, so dass es ein Objekt f (von mir geliefert) an den Block übergeben, anstatt zu versuchen, eine tatsächliche Datei zu öffnen? Etwas wie:

it "should test something" do 
    myobject = double("File", {'write' => true}) 
    File.should_receive(:open).with(&blk) do |myobject| 
     f.should_receive(:write) 
     blk.should_receive(:yield) (or somethig like that) 
    end 
end 
+1

Es ist schwierig, dies zu testen, da das, was Sie testen möchten, intern in der Methode ist. Wie interagiert Ihre Datei mit etwas außerhalb der Methode? In Ihrem Beispiel verwenden Sie die Datei nicht außerhalb der Methode, und Sie erhalten sie auch nicht. Wenn etwas außerhalb dieser Funktion die Datei benötigt, sollten Sie vielleicht erwägen, das Dateiobjekt an die Methode zu übergeben (Dependency-Injektion). Dann kannst du der Datei kein Problem machen. Wenn Sie etwas über diese Datei testen müssen, sollten Sie vielleicht überlegen, sie in eine separate Methode aufzuteilen? – Raj

+0

Danke ... tat so etwas, in mehrere Methoden aufgeteilt, stubed einige Funktionen wie File.stub (open) .and_yield (my_double), etc. – constantine1

Antwort

3

Ich denke, was Sie suchen sind yield matchers, das heißt:

it "should test something" do 
    # just an example 
    expect { |b| my_object.start(&b) }.to yield_with_no_args 
end 
+0

Wie stub ich File.open, um ein Mock-Objekt innerhalb der Funktion (Start) getestet werden? – constantine1

+0

Lassen Sie mich wiederholen - wie stub Datei.open, um ein Mock-Objekt zu seinem Block zu liefern, so dass ich etwas wie f.should_receive (: write) .with ("was in die Datei geschrieben werden soll") – constantine1

+0

Ich habe verpasst Ihr Kommentar und nur heute auf "Antworten" geklickt. Grundsätzlich sendet File.open den Block * self * (versuchen Sie 'puts f.inspect' aus dem Block heraus), also sollte' 'should_receive (: write)' 'spotten. Entschuldigung für die späte Antwort, aber hoffentlich wäre das nützlich für jemanden :) – Amir

1

Ihre andere Wahl zu Stub: offen mit einem neuen Objekt der Datei, wie zum Beispiel:

file = File.new 
allow(File).to receive(:open) { file } 
file.each { |section| expect(section).to receive(:write) } 
# run your method 
+0

Seien Sie vorsichtig damit. Ich habe in meiner Erfahrung festgestellt, dass, wenn Sie RSpec Stubs/Mocks auf grundlegende Systemklassen wie 'File' verwenden, es zu einer Menge von Problemen führt. Wenn Sie zum Beispiel den VCR-Edelstein in Ihren Tests verwenden, wird er auf spektakuläre Weise brechen, wenn Sie (Datei) zulassen, um so ziemlich alles zu empfangen. – Jazz