如何测试在给出块时调用方法

时间:2014-11-26 10:34:56

标签: ruby rspec

如果给出了一个块,我的任务是为以下简化方法编写rspec测试。没有给出阻止的情况已经过测试。

def make_something(name_id)
  name = find_name_by_id(name_id)
  if block_given? and name
    yield(something)
    name.save
  end
  name
end

测试是否有东西是没有问题的,但是如果调用name.save,我就会遇到问题。 我会这样做:

let!(:name) { create(:name) }
describe "when given a block" do
  #works
  it "yields something" do
    expect { |b| subject.make_something(name.id, &b)}.to yield_with_args(something)
  end 

  #1. try: doesn't work
  it "saves the name" do
    expect(name).to receive(:save)
    subject.make_something(name.id) {}
  end

  #2. try: also doesn't work
  it "saves the name" do
    expect(name).to receive(:save)
    subject.make_something(name.id) {|b|}
  end
end

我很害羞,解决方案很明显,但我找不到它。

1 个答案:

答案 0 :(得分:0)

我会尝试这样的事情:

let!(:name) { create(:name) }

describe "when given a block" do
  before do
    allow(subject).to receive(:find_name_by_id).with(name.id).and_return(name)
    allow(name).to receive(:save).and_call_original
  end

  it "yields something" do
    expect { |b| 
      subject.make_something(name.id, &b)
    }.to yield_with_args(something)
  end 

  it "saves the name" do
    subject.make_something(name.id) {}
    expect(name).to have_received(:save)
  end
end

关键思想是将find_name_by_id方法存根,以返回由name创建的同一let!实例。如果你不这样做,你的规范就会失败,因为你希望在save的一个实例中调用name,但它实际上是在另一个实例上调用的。