web-dev-qa-db-ja.com

依存性をテストする方法:RSpecで:destroy?

Userモデルの関連付けをテストしたいhas_many :projects, dependent: :destroyそして今のところこれまで行ってきました:

it "destroys dependent projects" do
  user = FactoryGirl.build(:user)
  project = FactoryGirl.build(:project)

  user.projects << project
  user.destroy

  expect(Project.count).to change(-1)
end

しかし、これはエラーを出します:

Failure/Error: expect(Project.count).to change(-1)
     ArgumentError:
       `change` requires either an object and message (`change(obj, :msg)`) or a block (`change { }`). You passed an object but no message.

ですから、changeは正しいマッチャーではないと思いますよね?エラーが発生しないでこのテストを作成する方法を教えていただけますか?

23
Xeen

それは正しいマッチャーですが、あなたはそれを正しい方法で使用していません:

  • 実行するアクションを含むブロックを受け取る必要があると予想します(この場合、ユーザーを削除します)
  • changeは、変更が予想される数値を生成するブロックを受け取る必要があります(rspecが名前付きメソッドを呼び出す必要があることを示すオブジェクトとシンボルを受け取ることもできます)

正しい方法は

expect { user.destroy }.to change { Project.count }

これは単に数値が変化することを主張するだけで、どの程度かを指定するものではありません。そのためには、byへの呼び出しをチェーンします。

expect { user.destroy }.to change { Project.count }.by(-1)
27

Shouldaマッチャーを使用することもできます。

it { expect(user).to have_many(:projects).dependent(:destroy) }

https://github.com/thoughtbot/shoulda-matchers

34
santuxus

これはうまくいくはずです:

expect { user.destroy }.to change { Project.count }.by(-1)
3
Marek Lipka

実際のプロジェクトの削除をテストする必要があります。

expect(Project.all).not_to include project
1
vanboom