在RSpec中测试默认范围

rct*_*eil 12 testing rspec ruby-on-rails rspec-rails

我正在尝试在模型中测试我的默认范围行.

我的测试如下:

it 'orders by ascending name by default' do
  expect(Coaster.scoped.to_sql).to eq Coaster.order(:name).to_sql
end
Run Code Online (Sandbox Code Playgroud)

我的错误是:

expected: "SELECT \"coasters\".* FROM \"coasters\"  ORDER BY name ASC, name"
got: "SELECT \"coasters\".* FROM \"coasters\"  ORDER BY name ASC"
Run Code Online (Sandbox Code Playgroud)

, name错误第一行末尾的部分是什么意思,我该如何解决这个问题呢?

更新:

我的测试:

  describe 'default scope' do
    let!(:coaster_one) { FactoryGirl.create(:coaster, name: "Tower of Terror") }
    let!(:coaster_two) { FactoryGirl.create(:coaster, name: "Apocalypse") }

    it 'orders by ascending name' do
      Coaster.all.should eq [:coaster_two, :coaster_one]
    end
  end
Run Code Online (Sandbox Code Playgroud)

我的错误:

expected: [:coaster_two, :coaster_one]
            got: [#<Coaster id: 5, name: "Apocalypse", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 408, created_at: "2013-07-23 20:48:52", updated_at: "2013-07-23 20:48:52", slug: "apocalypse-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>, #<Coaster id: 4, name: "Tower of Terror", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 407, created_at: "2013-07-23 20:48:52", updated_at: "2013-07-23 20:48:52", slug: "tower-of-terror-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>]

       (compared using ==)
Run Code Online (Sandbox Code Playgroud)

更新2:

看起来Rails 4似乎不赞成使用default_scope,所以鉴于此,我从我的模型中删除了default_scope并将其替换为标准范围.

新范围现在是:

scope :by_name_asc, lambda { order("name ASC") }
Run Code Online (Sandbox Code Playgroud)

我的相关测试是:

  describe 'scopes' do
    let!(:coaster_one) { FactoryGirl.create(:coaster, name: "Tower of Terror") }
    let!(:coaster_two) { FactoryGirl.create(:coaster, name: "Apocalypse") }

    it "orders coasters by ascending name" do
      Coaster.by_name_asc.should eq [:coaster_two, :coaster_one]
    end
  end
Run Code Online (Sandbox Code Playgroud)

运行此测试时,我得到:

  1) Coaster scopes orders coasters by ascending name
     Failure/Error: Coaster.by_name_asc.should eq [:coaster_two, :coaster_one]

       expected: [:coaster_two, :coaster_one]
            got: [#<Coaster id: 15, name: "Apocalypse", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 528, created_at: "2013-07-24 22:36:50", updated_at: "2013-07-24 22:36:50", slug: "apocalypse-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>, #<Coaster id: 14, name: "Tower of Terror", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 527, created_at: "2013-07-24 22:36:50", updated_at: "2013-07-24 22:36:50", slug: "tower-of-terror-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>]

       (compared using ==)

       Diff:
       @@ -1,2 +1,2 @@
       -[:coaster_two, :coaster_one]
       +[#<Coaster id: 15, name: "Apocalypse", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 528, created_at: "2013-07-24 22:36:50", updated_at: "2013-07-24 22:36:50", slug: "apocalypse-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>, #<Coaster id: 14, name: "Tower of Terror", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 527, created_at: "2013-07-24 22:36:50", updated_at: "2013-07-24 22:36:50", slug: "tower-of-terror-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>]

     # ./spec/models/coaster_spec.rb:10:in `block (3 levels) in <top (required)>'
Run Code Online (Sandbox Code Playgroud)

什么是错误的任何想法?

Moh*_*mad 17

测试默认范围的更好方法是使用具有预期输出的实际数据.为您的类创建虚拟对象,然后查询该类并将结果与​​您期望的正确顺序进行比较:

describe 'default scope' do
  let!(:book_one) { Book.create(name: "The Count of Monte Cristo") }
  let!(:book_two) { Book.create(name: "Animal Farm") }

  it 'orders by ascending name' do
    Book.all.should eq [book_two, book_one]
  end
end
Run Code Online (Sandbox Code Playgroud)

let!(:book_one)创建一个实例Book并将其分配给一个名为的局部变量book_one.它的name属性是基督山伯爵.let!(:book_two)做类似的事情.

如果默认顺序是name ASC,则查询Book模型应该返回ActiveRecord关系book_two作为第一个元素("Animal ..."),并book_one作为第二个元素("C ...").

我们可以测试这个期望如下:

Book.all.should eq [book_two, book_one]
Run Code Online (Sandbox Code Playgroud)

这不会测试您的SQL,但会测试代码的直接输出,这更有用.它也与数据库无关.