RSpec,期望随多个值而变化

时间:2012-12-20 05:45:08

标签: ruby-on-rails rspec

  

可能重复:
  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块只能执行一次,因为表单已经提交。

我知道我可以制造另一个“它”块,但我觉得必须有一个干燥方式。

2 个答案:

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