如何测试 dependent: :destroy with RSpec?

How to test dependent: :destroy with RSpec?

我想测试我的 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 不是正确的匹配器,是吗?你能告诉我如何编写这个测试而不出现那个错误吗?

这应该有效:

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

它是正确的匹配器,但您没有以正确的方式使用它:

  • expect 需要接收包含要执行的操作的块(在您的情况下删除用户)
  • change 需要接收一个产生预期变化的数值的块(它也可以接收一个对象和一个符号,表明 rspec 应该调用指定的方法)

正确的做法是

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

这里只是断言数值发生了变化,并没有说明变化了多少。为此,将调用链接到 by:

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

您应该测试实际项目的删除。

expect(Project.all).not_to include project

你也可以使用 shoulda 匹配器:

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

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

这应该有效:

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