2014-09-26 184 views
0

我对FactoryGirl和RSpec有问题。我有以下测试:使用Rspec let进行测试失败

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 

它可以正常工作。为什么我的例子与失败?

+0

向您的工厂展示 – BroiSatse 2014-09-26 10:23:32

回答

3

这是因为let被懒惰地评价。

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

第二个letcreate(:address, ...)直到调用eq address才被调用。

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

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

另一种选择是使用自定义的工厂customer_with_address那台association