如何在阻止之前“期望”改变rspec中的某些内容?

时间:2013-05-22 20:25:47

标签: ruby rspec

我有一个以这种方式构建的测试套件:

let(:cat) { create :blue_russian_cat } 
subject { cat }

context "empty bowl" do
  let!(:bowl) { create(:big_bowl, amount: 0) }
  before { meow }

  # a ton of `its` or `it` which require `meow` to be executed before making assertion
  its(:status) { should == :annoyed }
  its(:tail) { should == :straight }
  # ...

  # here I want to expect that number of PetFishes is going down after `meow`, like that
  it "will eat some pet fishes" do
    expect {???}.to change(PetFish, :count).by(-1)
  end
end

通常我只是将这个块放在上下文之外,调用expect就像那样:

  it "will eat some pet fishes" do
    expect { meow }.to change(PetFish, :count).by(-1)
  end

但它使代码更难阅读,因为相关代码被置于其上下文之外。

3 个答案:

答案 0 :(得分:4)

您是否会考虑将测试更改为expect语法,以使它们位于同一context下?也许是这样的事情:

let(:cat) { create :blue_russian_cat } 

context "empty bowl" do
  let!(:bowl) { create(:big_bowl, amount: 0) }
  let(:meowing) { -> { meow } } # not sure what meow is, so may not need lambda

  it "will annoy the cat" do
    expect(meowing).to change(cat.status).from(:placid).to(:annoyed)
  end

  # here I want to expect that number of PetFishes is going down after `meow`
  it "will eat some pet fishes" do
    expect(meowing).to change(PetFish, :count).by(-1)
  end
end

答案 1 :(得分:3)

您没有对before阻止设置期望。它的目的是设置环境(以及它在规范之前执行,所以现在为时已晚,不能指望它)。您需要定期let

context "empty bowl" do
  let(:cat) { meow }

  # here I want to expect that number of PetFishes is going down after `meow`, like that
  it "will eat some pet fishes" do
    expect {cat}.to change(PetFish, :count).by(-1)
  end
end

答案 2 :(得分:0)

我意识到使用实例变量并不理想,但如果你的敏感性允许,你可以这样做:

context "empty bowl" do
  # ...
  before { @pet_fish_change = change_to(PetFish, :count) {meow} }

  it "will eat some pet fishes" do
    expect(@pet_fish_change).to eq(-1)
  end

  # ...

end

这要求您定义change_to辅助方法,但这非常简单:

def change_to(obj, method, &block)
  before = obj.send method
  yield
  (obj.send method) - before
end