13

可能重复:
RSpec 是否有可能期望在两个表中发生变化?

it "should create a new Recipe" do
  expect { click_button submit }.to change(Recipe, :count).by(1)
end

这使我可以检查“食谱”模型是否还有一个条目,但我还想检查“成分”模型是否还有一个条目。expect 块只能执行一次,因为表单已经提交。

我知道我可以再做一个“它”块,但我觉得必须有一个 DRYer 方法。

4

2 回答 2

51

我建议通过重新定义测试对象(并使用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

更新:虽然它可能看起来不那么 DRY,但这些天我可能仍会继续使用该expect语法,因为它是推荐的,而且我通常会远离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 文档中change看到expect使用大括号的匹配器。这当然是正确的,但标准括号在此示例中起作用的原因是更改可变状态(包含在 中)的代码位于作为参数creating_a_recipe传入时被调用的 lambda 中。expect

无论如何,在这种情况下,expect(creating_a_recipe)或者expect { creating_a_recipe }可以成功使用,您使用哪个取决于个人喜好。

于 2012-12-20T06:38:13.377 回答
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
于 2012-12-20T06:11:15.037 回答