我怎样才能对我的默认范围进行 rspec 测试

发布于 2024-11-26 20:27:42 字数 433 浏览 2 评论 0原文

我的模型有 default_scope(:order => 'created_at' ) 我的测试(rspec、工厂女孩、shoulda 等) 是:

require 'spec/spec_helper.rb'

describe CatMembership do
  context "is valid" do
    subject { Factory.build(:cat_membership) }
    it { should be_valid }
    it { should belong_to :cat}
    it { should belong_to :cat_group}
    it { should have_db_column(:start_date)}
    it { should have_db_column(:end_date)}
  end
end

my model has default_scope(:order => 'created_at' )
my tests (rspec, factory girl, shoulda, etc.)
are:

require 'spec/spec_helper.rb'

describe CatMembership do
  context "is valid" do
    subject { Factory.build(:cat_membership) }
    it { should be_valid }
    it { should belong_to :cat}
    it { should belong_to :cat_group}
    it { should have_db_column(:start_date)}
    it { should have_db_column(:end_date)}
  end
end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

俏︾媚 2024-12-03 20:27:42

我宁愿使用查询并检查结果进行测试,但如果您确实必须这样做,对于 Rails 3 来说,一种可能的解决方案是这样的:

CatMembership.scoped.to_sql.should == CatMembership.order(:created_at).to_sql

在 Rails 2 上:

CatMembership.default_scoping.should == [{:create=>{}, :find=>{:order=>"created_at"}}]

但我不会说这些解决方案是理想的,因为它们显示了很多实现方面的知识(并且您可以看到不同 Rails 版本的实现有所不同)。

创建示例数据、运行通常的 all 查询并检查结果是否正确排序可能会更简单,更接近真实的单元测试,并且即使升级 Rails 版本也能正常工作。

在这种情况下,它可能是:

before do
  @memberships = []

  @memberships << CatMembership.create!
  @memberships << CatMembership.create!
  @memberships << CatMembership.create!

  [ 1.hour.ago, 5.minutes.ago, 1.minute.ago ].each_with_index do |time, index|
    membership = @memberships[index]
    membership.created_at = time
    membership.save
  end

end

it 'should be correctly ordered' do
  @sorted_memberships = CatMembership.all
  @memberships.first.should == @sorted_memberships.last
  @memberships.second.should == @sorted_memberships.second
  @memberships.third.should == @sorted_memberships.first
end

它更加冗长,但即使您在轨道上前进,它也会起作用。

现在我刚刚注意到是谁问了这个问题:D

I would rather have this tested using a query and checking the results, but if you really must do it, one possible solution would be something like this for Rails 3:

CatMembership.scoped.to_sql.should == CatMembership.order(:created_at).to_sql

And on Rails 2:

CatMembership.default_scoping.should == [{:create=>{}, :find=>{:order=>"created_at"}}]

But I would not say these solutions are ideal since they show a lot of knowledge of the implementation (and you can see the implementation varies with different Rails versions).

Creating sample data, running an usual all query and checking the result is correctly ordered might have been simpler, would be closer to real unit testing and would work even as you upgrade your rails version.

In this case it would possibly be:

before do
  @memberships = []

  @memberships << CatMembership.create!
  @memberships << CatMembership.create!
  @memberships << CatMembership.create!

  [ 1.hour.ago, 5.minutes.ago, 1.minute.ago ].each_with_index do |time, index|
    membership = @memberships[index]
    membership.created_at = time
    membership.save
  end

end

it 'should be correctly ordered' do
  @sorted_memberships = CatMembership.all
  @memberships.first.should == @sorted_memberships.last
  @memberships.second.should == @sorted_memberships.second
  @memberships.third.should == @sorted_memberships.first
end

It's much more verbose, but it's going to work even as you move forward on rails.

And now I have just noticed who asked the question :D

海拔太高太耀眼 2024-12-03 20:27:42

干燥它,使用共享示例

最有可能的是,您将拥有多个具有相似默认范围的模型(如果没有,大多数情况下会忽略此方法),因此您可以将此 Rspec 示例放入共享示例中,您可以在其中从各种类型中调用它型号规格。

我检查默认范围的首选方法是确保默认的 ActiveRecord::Relation 具有预期的子句(orderwhere 或任何情况可能是),如下所示:

spec/support/shared_examples/default_scope_examples.rb

shared_examples_for 'a default scope ordered by created_at' do

  it 'adds a clause to order by created_at' do
    described_class.scoped.order_clauses.should include("created_at")
  end

end

然后在您的 CatMembership 规范(以及具有相同默认范围的任何其他规范)中,所有你需要的是:

spec/models/cat_membership_spec.rb

describe CatMembership

  it_behaves_like 'a default scope ordered by created_at'

  # other spec examples #

end

最后,您可以看到如何将此模式扩展到各种默认范围,并保持事物干净、有组织,最重要的是,DRY。

DRY It Up, Use Shared Examples

Most likely, you'll have more than one model with a similar default scope (if not, mostly ignore this method) so you can put this Rspec example into a shared_example where you can call it from a variety of model specs.

My preferred method of checking a default scope is to make sure the default ActiveRecord::Relation has the expected clause (order or where or whatever the case may be), like so:

spec/support/shared_examples/default_scope_examples.rb

shared_examples_for 'a default scope ordered by created_at' do

  it 'adds a clause to order by created_at' do
    described_class.scoped.order_clauses.should include("created_at")
  end

end

And then in your CatMembership spec (and any other spec that has the same default scope), all you need to is:

spec/models/cat_membership_spec.rb

describe CatMembership

  it_behaves_like 'a default scope ordered by created_at'

  # other spec examples #

end

Finally, you can see how this pattern can be extended to all sorts of default scopes and keeps things clean, organized and, best of all, DRY.

够钟 2024-12-03 20:27:42

根据 RSpec 的最新约定,建议使用 expect 而不是 should 因此,更好的答案是

expect(CatMembership.scoped.to_sql) .to eq(CatMembership.order(:created_at).to_sql)

但是,最近 Model.scoped 已被弃用,因此建议使用Model.all 改为

expect(CatMembership.all.to_sql).to eq(CatMembership.order(:created_at).to_sql)

According to latest conventions of RSpec expect is recommended instead of should so, better answer would be

expect(CatMembership.scoped.to_sql).to eq(CatMembership.order(:created_at).to_sql)

However, lately Model.scoped is deprecated so it is recommended to use Model.all instead

expect(CatMembership.all.to_sql).to eq(CatMembership.order(:created_at).to_sql)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文