Ruby on rails 如何使用RSpec测试dependent::destroy?

Ruby on rails 如何使用RSpec测试dependent::destroy?,ruby-on-rails,ruby,unit-testing,testing,rspec,Ruby On Rails,Ruby,Unit Testing,Testing,Rspec,我想测试一下我的用户模型协会有很多:项目、依赖::销毁,现在已经走了这么远: 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 所以我认为cha

我想测试一下我的
用户
模型协会
有很多:项目、依赖::销毁
,现在已经走了这么远:

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
所以我认为
change
不是合适的匹配者,是吗?您能告诉我如何编写此测试而不出现错误吗?

这应该可以:

expect { user.destroy }.to change { Project.count }.by(-1)
it { is_expected.to have_many(:projects).dependent(:destroy) }

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

  • expect需要接收包含要执行的操作的块(在您删除用户的情况下)
  • change需要接收一个块,该块生成预期更改的数值(它还可以接收一个对象和一个符号,指示rspec应该调用命名方法)
正确的方法是

expect { user.destroy }.to change { Project.count }
这只是断言数值发生了变化,但没有指定变化的程度。为此,通过链接调用

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) }

这应该可以:

expect { user.destroy }.to change { Project.count }.by(-1)
it { is_expected.to have_many(:projects).dependent(:destroy) }

您应该在规范帮助程序中包括shoulda matchers:
需要'shoulda/matchers'
,有关依赖项的更多信息:是否有其他解决方案而不是使用shoulda matchers gem?
shoulda/matchers
需要,但是仍然抛出。当依赖项是依赖项但未在关联的shoulda matcher中指定时,它不会报告为错误。您可以编写expect
{user.destroy}。要更改(项目,:count)。通过(-1)
避免第二个阻塞我一直都是这样做的。然而,我更喜欢vanboom的答案,因为它更明确。虽然不太可能,但如果您有一个bug通过了.by(-1)变体,但没有通过更明确的测试,那么跟踪它将是一件痛苦的事情,从而大大提高了成本