我有一个以这种方式构建的测试套件:
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
但它使代码更难阅读,因为相关代码被置于其上下文之外。
答案 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