2013-07-31 50 views
11

mô hình/message.rb

class Message 

    attr_reader :bundle_id, :order_id, :order_number, :event 

    def initialize(message) 
    hash = message 
    @bundle_id = hash[:payload][:bundle_id] 
    @order_id = hash[:payload][:order_id] 
    @order_number = hash[:payload][:order_number] 
    @event = hash[:concern] 
    end 
end 

đặc tả/mô hình/message_spec.rb

require 'spec_helper' 

describe Message do 
    it 'should save the payload' do 
    payload = {:payload=>{:order_id=>138251, :order_number=>"AW116554416"}, :concern=>"order_create"} 
    message = FactoryGirl.build(:message, {:payload=>{:order_id=>138251, :order_number=>"AW116554416"}, :concern=>"order_create"}) 
    message.event.should == "order_create" 
    end 
end 

error_log

thất bại:nhà máy cô gái đi qua lập luận để mô hình định nghĩa về xây dựng/tạo

1) Tin nhắn nên lưu tải trọng

Failure/Error: message = FactoryGirl.build(:message, {:payload=>{:order_id=>138251, :order_number=>"AW116554416"}, :concern=>"order_create"}) 
ArgumentError: 
    wrong number of arguments (0 for 1) 
# ./app/models/message.rb:4:in `initialize' 
# ./spec/models/message_spec.rb:7:in `block (2 levels) in <top (required)>' 

Trả lời

17

FactoryGirl yêu cầu bạn xác định nhà máy trước tiên. Hãy nói rằng trong một file spec/nhà máy/messages.rb:

FactoryGirl.define do 
    factory :message do 
    bundle_id 1 
    order_id 2 
    ...etc... 
    end 
end 

Sau đó, bạn có thể gọi nhà máy xây dựng tạo ra như thế này:

FactoryGirl.build(:message) # => bundle_id == 1, order_id == 2 
FactoryGirl.build(:message, order_id: 3) # => bundle_id == 1, order_id == 3 

Tuy nhiên, có một vấn đề trong bạn trương hợp đ̣ăc biệt. Nhà xây dựng mặc định của FactoryGirl hoạt động trên cùng giao diện ActiveRecord. Nó đặt thuộc tính được xác định thông qua setters, không phải thông qua một hash của attrs truyền cho constructor mô hình:

m = Message.new 
m.bundle_id = 1 
m.order_id = 2 

Vì vậy, bạn phải tạo một constructor tùy chỉnh để làm việc với giao diện của mô hình của bạn (mà không phù hợp với ActiveRecord mô hình tương tự) và đăng ký nó theo định nghĩa nhà máy của bạn. Xem factory girl docs để biết chi tiết.

Hãy để tôi chỉ cho bạn một ví dụ về làm như vậy. Xin lỗi tôi đã không kiểm tra nó nhưng nó sẽ cung cấp cho bạn một đầu mối:

FactoryGirl.define do 
    factory :message do 
    ignore do 
     # need to make all attributes transient to avoid FactoryGirl calling setters after object initialization 
     bundle_id 1 
     order_id 2 
    end 

    initialize_with do 
     new(payload: attributes) 
    end 
    end 
end 
+0

Cần lưu ý rằng chỉ kể từ khi FactoryGirl 2.5 đã khởi tạo được hỗ trợ: http://robots.thoughtbot.com/factory-girl-2-5-gets-custom-constructors (điều này thực sự quan trọng nếu bạn đang bị mắc kẹt bằng cách sử dụng rspec 1.x do các vấn đề phụ thuộc) – Lambart

+0

Cũng lưu ý: 'CẢNH BÁO KHÔNG CẦN: \' #ignore \ 'không được chấp nhận và sẽ bị xóa trong 5.0. Vui lòng sử dụng \ '#transient \' thay thế.' – thisismydesign

0

Đó là bởi vì bạn có một nhà xây dựng với các đối số bắt buộc. Bạn có một vài lựa chọn; !

1) Hãy lập luận không bắt buộc (mặc dù điều này có nghĩa là bạn đang thay đổi mã của bạn cho phù hợp với các bài kiểm tra của bạn - nghịch ngợm)

def initialize(message = nil) 

2) Sử dụng "initialize_with" cú pháp trong nhà máy của bạn;

describe Message do 
    it 'should save the payload' do 
    payload = {:payload=>{:order_id=>138251, :order_number=>"AW116554416"}, :concern=>"order_create"} 
    message = FactoryGirl.build(:message, {:payload=>{:order_id=>138251, :order_number=>"AW116554416"}, :concern=>"order_create"}) 
    message.event.should == "order_create" 
    end 

    initialize_with { new(message) } 
end