13

重複の可能性:
RSpec が 2 つのテーブルの変更を予期することは可能ですか?

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

これにより、「レシピ」モデルにもう 1 つのエントリがあることを確認できますが、「材料」モデルにもう 1 つのエントリがあることも確認したいと思います。フォームは既に送信されているため、expect ブロックは 1 回しか実行できません。

別の 'it' ブロックを作成できることはわかっていますが、もっとドライな方法が必要だと感じています。

4

2 に答える 2

51

私は、テスト対象を再定義することによってそれを乾燥させることを提案します (そして楽しみのために安定したラムダを使用します):

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 のドキュメントを参照しくださいchangeexpect。これはもちろん正しいですが、この例で標準の括弧が機能する理由は、変更可能な状態を変更するコード ( に含まれる) が、パラメーターとしてcreating_a_recipe渡されたときに呼び出されるラムダにあるためです。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

ただし、多くのモデルでこれを行う場合にのみお勧めします。そうしないと、コードが読みにくくなります。もしそうなら、specヘルパーに入れるのが最善です。

また、テストの他の前例に基づいて、文字列の代わりに Const オブジェクトを渡すこともできます (上記の例で使用したように)。

それから

it "should create a new Recipe" do
  test_creation_of( 'Recipe' )
  test_creation_of( 'Ingredient' )
end
于 2012-12-20T06:11:15.037 に答える