可能重复:
Is it possible for RSpec to expect change in two tables?
it "should create a new Recipe" do
expect { click_button submit }.to change(Recipe, :count).by(1)
end
这允许我检查'Recipe'模型还有一个条目,但我还想检查'Ingredient'模型还有一个条目。 expect块只能执行一次,因为表单已经提交。
我知道我可以制造另一个“它”块,但我觉得必须有一个干燥方式。
答案 0 :(得分:48)
我建议通过重新定义测试主题来干燥它(并使用stabby lambdas来获得乐趣):
describe "recipe creation" do
subject { -> { click_button submit } }
it { should change(Recipe, :count).by(1) }
it { should change(Ingredient, :count).by(1) }
end
更新:虽然它可能看起来不那么干,但是现在我可能会继续使用expect
语法,因为它是recommended而我通常会离开来自should
,但可能会对规格可读性做一些小改动:
describe "recipe creation" do
let(:creating_a_recipe) { -> { click_button submit } }
it "changes the Recipe count" do
expect(creating_a_recipe).to change(Recipe, :count).by(1)
end
it "changes the Ingredient count" do
expect(creating_a_recipe).to change(Ingredient, :count).by(1)
end
end
注意:您可能会在RSpec documentation for the change
matcher中看到expect
使用大括号。当然,这是正确的,但是此示例中标准括号的工作原因是更改可变状态的代码(包含在creating_a_recipe
中)是在传入expect
时被调用的lambda中作为参数。
无论如何,在这种情况下,expect(creating_a_recipe)
或expect { creating_a_recipe }
都可以成功使用,无论您使用的是个人偏好。
答案 1 :(得分:0)
您可以将所有这些抽象为辅助方法
def test_creation_of(model)
it "should create a new #{model}" do
expect { click_button submit }.to change(model.constantize, :count).by(1)
end
end
但是如果你要为很多型号做这件事,我只会推荐它。否则它只会使代码更难阅读。如果你这样做,最好将它放入规范助手。
此外,根据测试中的其他先例,您可以传递Const对象而不是字符串(就像我在上面的示例中所使用的那样)。
然后
it "should create a new Recipe" do
test_creation_of( 'Recipe' )
test_creation_of( 'Ingredient' )
end