has_many 与 RSpec 关系中的测试顺序

Test order in has_many relationship with RSpec

我对 Rails 和 RSpec 不是很有经验,并且经常在编写测试时遇到麻烦。所以,我的下一个麻烦是我不知道如何正确测试模型关系中的顺序。

假设我有这样的简单模型:

class Kitchen < ActiveRecord::Base
  has_many :orders, -> { order(completed_at: :desc) }
end

以及该模型的简单测试:

require 'rails_helper'

RSpec.describe Kitchen, :type => :model do
  before { @kitchen = FactoryGirl.create(:kitchen) }

  subject { @kitchen }

  describe "orders" do
    before do
      @kitchen.orders.build(description: "Test description 1",
        completed_at: 1.day.ago.localtime)

      @kitchen.orders.build(description: "Test description 2",
        completed_at: Time.now)
    end

    it "should be sorted by completion date in descending order" do
      expect(@kitchen.orders.first.completed_at).to be > @kitchen.orders.last.completed_at
    end
  end
end

结果我得到了错误:

Failure/Error: expect(@kitchen.orders.first.completed_at).to be > @kitchen.orders.last.completed_at
   expected: > Fri, 15 May 2015 12:21:54 UTC +00:00
        got:   Thu, 14 May 2015 12:21:54 UTC +00:00

任何帮助将不胜感激。

您正在使用 build。这不会保留到数据库中,因此当您调用 @kitchen.orders.first 时,您不会访问数据库,只是取回您创建的第一个,这是错误的。

改用create,然后调用@kitchen.reload从数据库刷新。

我会这样做:

RSpec.describe Kitchen, :type => :model do
  let(:kitchen) { FactoryGirl.create(:kitchen) }

  describe 'orders' do
    let(:yesterday) { 1.day.ago }
    let(:today)     { Time.now }

    before do
      # `create` actually saves the objects into the database
      kitchen.orders.create(description: '1', completed_at: today)
      kitchen.orders.create(description: '2', completed_at: yesterday)
    end

    # `(true)` forces a reload of the associated objects
    subject(:orders) { kitchen.orders(true) } 

    it 'should be sorted by completion date in descending order' do
      expect(orders.map(&:completed_at)).to eq [yesterday, today]
    end
  end
end

下面的怎么样:

it {
    is_expected.to have_many(:orders).order( completed_at: :desc )
}