RSpec - 模拟&符号参数

时间:2012-03-22 13:20:35

标签: ruby rspec mocking

我有以下代码

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 个答案:

答案 0 :(得分:4)

好的,我现在明白了发生了什么。 这段代码不仅仅是将对象发送到方法。

bar.map(&:to_sym)

“map方法,从”混入“模块Enumerable到Array类,为self的每个元素调用一次block参数,在本例中为数组,并返回一个包含返回值的新数组但是在这种情况下,我们没有一个块,我们有&大写.....当一个一元&符号被添加到Ruby中的一个对象时,如果该对象不是Proc对象,那么解释器尝试通过调用to_proc将对象转换为proc。因为:capitalize是一个Symbol,而不是Proc,Ruby一起发送并将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

答案 1 :(得分:0)

方法#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

答案 2 :(得分:0)

谢谢大家的提问。最后,我来到以下代码。它没有为#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