2013-02-19 17 views
10

Mam funkcję, która przyjmuje blok, otwiera plik, plony i zyski:Jak przetestować funkcję, która przyjmuje blok z RSpec

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

Próbuję napisać test na to używając RSpec . W jaki sposób I stub plik File.open, aby przekazać obiekt f (dostarczone przeze mnie) do bloku zamiast próbować otworzyć rzeczywisty plik? Coś jak:

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

Trudno to przetestować, ponieważ to, co chcesz przetestować, jest wewnętrzną metodą. W jaki sposób twój plik wchodzi w interakcję z czymkolwiek poza tą metodą? Z Twojego przykładu nie korzystasz w ogóle z pliku spoza metody, a ty go również nie uzyskujesz. Jeśli coś poza tą funkcją potrzebuje pliku, to może warto rozważyć przekazanie obiektu do pliku do metody (wtrysk zależności). Wtedy możesz kpić z pliku bez problemu. Jeśli potrzebujesz przetestować coś na temat tego pliku, może powinieneś rozważyć podzielenie go na osobną metodę? – Raj

+0

Dzięki ... zrobiłem coś takiego, podzielone na wiele metod, zgasiłem kilka funkcji, takich jak File.stub (open) .and_yield (my_double), itp. – constantine1

Odpowiedz

3

myślę co szukasz są yield matchers, tj:

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

Jak I stub a File.open do dostarczania próbnego obiektu wewnątrz funkcji (start) podczas testów? – constantine1

+0

Powtórzę - w jaki sposób mogę wstawić File.open, aby dostarczyć fałszywy obiekt do jego bloku, tak żebym mógł przetestować coś w stylu f.should_receive (: write) .with ("co powinno być zapisane w pliku") – constantine1

+0

Tęskniłem Twój komentarz i dopiero dziś kliknąłeś "odpowiedzi". Zasadniczo File.open wysyła blok * self * (spróbuj uruchomić 'puts f.inspect' z wnętrza bloku), więc powinno działać szyderstwo' File.should_receive (: write) '. Przepraszam za spóźnioną odpowiedź, ale mam nadzieję, że byłoby to przydatne dla kogoś :) – Amir

1

Twoje innego wyboru jest odgałęzienie: otwarta z nowym obiektem pliku, takie jak:

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

Ostrożnie z tym. Z mojego doświadczenia wynika, że ​​jeśli używasz kodów pośredniczących/makr RSpec w podstawowych klasach systemowych, takich jak 'File', to prowadzi to do wielu problemów. Na przykład, jeśli użyjesz klejnotu VCR w twoich testach, pęknie on w spektakularny sposób, jeśli pozwolisz (File) .otrzymać prawie wszystko. – Jazz