使用Rspec测试失败

时间:2014-09-26 10:10:44

标签: ruby-on-rails ruby rspec factory-bot

我对FactoryGirl和RSpec有问题。我有以下测试:

require 'rails_helper'
describe Customer do
  it_behaves_like "Account"

  describe "it has an address" do
    let(:customer) {create(:customer)}
    let(:address) {create(:address, addressable_id: customer.id, addressable_type: "Account")}

    it "should have an address" do
      expect(customer.address).to eq address
    end
  end
end

当我尝试运行它时会抛出以下错误:

) Customer it has an address should have an address
     Failure/Error: expect(customer.address).to eq address

       expected: #<Address id: 1, street: "Street 1", zip_code: "11-111", city: "City 1", addressable_id: 1, addressable_type: "Account", created_at: "2014-09-26 10:07:51", updated_at: "2014-09-26 10:07:51">
            got: nil

       (compared using ==)
     # ./spec/models/customer_spec.rb:11:in `block (3 levels) in <top (required)>'

但是当我把它重构成这样的东西时:

require 'rails_helper'

describe Customer do
  it_behaves_like "Account"

  describe "it has an address" do
    before do
      @customer = create(:customer)
      @address = create(:address, addressable_id: @customer.id, addressable_type: "Account")
    end

    it "should have an address" do
      expect(@customer.address).to eq @address
    end
  end
end

它运作正常。为什么我的let示例失败了?

1 个答案:

答案 0 :(得分:3)

因为let被懒惰地评估了。

致电expect(customer.address)会调用您的第一个let阻止,即create(:customer)。它会返回一个没有地址的customer

在调用let之前,不会调用第二个create(:address, ...)eq address

您可以使用let!立即创建地址:

let!(:address) { create(:address, ...) }

另一种选择是使用自定义工厂customer_with_address来设置association