我对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示例失败了?
答案 0 :(得分:3)
因为let
被懒惰地评估了。
致电expect(customer.address)
会调用您的第一个let
阻止,即create(:customer)
。它会返回一个没有地址的customer
。
在调用let
之前,不会调用第二个create(:address, ...)
块eq address
。
您可以使用let!
立即创建地址:
let!(:address) { create(:address, ...) }
另一种选择是使用自定义工厂customer_with_address
来设置association。