2013-02-19 3 views
10

У меня есть функция, которая принимает блок, открывает файл, урожайность и возвращает:Как проверить функцию, которая принимает блок с RSpec

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

Я пытаюсь написать тест для него с помощью RSpec , Как заполнить файл File.open так, чтобы он передал объект f (предоставленный мной) блоку вместо того, чтобы пытаться открыть фактический файл? Что-то вроде:

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

Трудно проверить это, потому что то, что вы хотите проверить, является внутренним для метода. Как ваш файл взаимодействует с чем-либо вне метода? В вашем примере вы вообще не используете файл вне метода, и вы его тоже не уступаете. Если что-то вне этой функции нуждается в файле, возможно, вам стоит рассмотреть возможность передачи объекта файла в метод (инъекция зависимостей). Тогда вы можете высмеять файл без проблем. Если вам нужно проверить что-то об этом файле, возможно, вам стоит рассмотреть возможность разбить его на отдельный метод? – Raj

+0

Спасибо ... сделал что-то вроде этого, разбил на несколько методов, заколол несколько функций, таких как File.stub (open) .and_yield (my_double) и т. Д. – constantine1

ответ

3

Я думаю, что вы ищете являются yield matchers, то есть:

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

Как заглушить File.open, чтобы снабдить макет объекта внутри функции (начало). – constantine1

+0

Позвольте мне повторить - как я могу заглушить File.open, чтобы предоставить макет объекта его блоку, чтобы я мог проверить что-то вроде f.should_receive (: write) .with («что должно быть записано в файл») – constantine1

+0

Я пропустил ваш комментарий и только сегодня нажал на «ответы». В основном File.open отправляет блок * self * (попробуйте запустить 'puts f.inspect' изнутри блока), поэтому надоедать' File.should_receive (: write) 'должно работать. Извините за поздний ответ, но, надеюсь, это было бы полезно кому-то :) – Amir

1

Ваш другой выбор должен шлейфом: открыт с новым объектом File, как таковой:

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

Будьте осторожны с этим. Я нашел в своем опыте, что если вы используете RSpec stubs/mocks на базовых системных классах, например 'File', это приводит к множеству проблем. Например, если вы используете камень VCR в своих тестах, он будет поражать эффектно, если вы позволите (File) получить почти что угодно. – Jazz