RSpec - фиктивные параметры амперсанда и символа - PullRequest
2 голосов
/ 22 марта 2012

У меня есть следующий код

def foo(bar)
  bar.map(&:to_sym)
end

Я хочу установить ожидание на map с &:to_sym.Если я сделаю

describe '#foo' do
  it 'should convert to array of symbols' do
    bar = %w(test1 test2)
    bar.should_receive(:map).with(&:to_sym)
    foo(bar)
  end
end

Не получится

ArgumentError: no receiver given

Есть идеи, как мне это сделать?

Ответы [ 3 ]

4 голосов
/ 24 марта 2012

Хорошо, теперь я понимаю, что происходит.Этот фрагмент кода делает гораздо больше, чем просто отправка объекта в метод.

bar.map(&:to_sym)

"Метод map из модуля Enumerable, который« смешивается »с классом Array, вызывает блокаргумент один раз для каждого элемента self, в данном случае для массива, и возвращает новый массив, содержащий значения, возвращаемые блоком. Однако в этом случае у нас нет блока, у нас есть &: capitalize .....Когда к объекту в Ruby добавляется унарный амперсанд, если этот объект не является объектом Proc, интерпретатор пытается преобразовать объект в процесс, вызывая для него to_proc.и отправляет сообщение to_proc по адресу: capitalize, .. "http://swaggadocio.com/post/287689063

http://pragdave.pragprog.com/pragdave/2005/11/symbolto_proc.html

В основном вы пытаетесь проверить, что блок передается в #map, который я надеваюне верю, что вы можете сделать в rspec.По сути, это:

    bar.map {|element| element.to_sym}

Я бы также сказал, что этот тест во многом зависит от деталей реализации #foo, что делает тест хрупким, поскольку код внутри метода часто изменяется при рефакторинге.,Вместо этого вы должны проверить, что метод возвращает правильное значение.

    describe '#foo' do
      it 'should convert to array of symbols' do
        bar = %w(test1 test2)
        foo(bar).should == [:test1 , :test2]
      end
    end
0 голосов
/ 26 марта 2012

Спасибо всем за вопрос. Наконец, я пришел к следующему коду. Он не устанавливает ожидания для #map, но гарантирует, что каждый элемент массива преобразуется в символ:

def foo(bar)
  bar.map(&:to_sym)
end

describe '#foo' do
  it 'should convert to array of symbols' do
    bar = %w(test1 test2)
    bar.each do |i|
      sym = i.to_sym
      i.should_receive(:to_sym).and_return(sym)
    end
    foo(bar)
  end
end
0 голосов
/ 23 марта 2012

Метод #foo ожидает аргумент, который вы не предоставили

describe '#foo' do
  it 'should convert to array of symbols' do
    bar = %w(test1 test2)
    bar.should_receive(:map).with(&:to_sym)
    foo(bar) #change your original line to this
  end
end
...