2013-07-31 2 views
11

модели/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 

спецификация/модель/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

Неудачи:завод девушка передать аргументы модель определения по сборке/создавать

1) Сообщение должно сохранить полезную нагрузку

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)>' 

ответ

17

FactoryGirl требует, чтобы вы сначала определили завод. Скажем, в файле спецификации/фабрик/messages.rb:

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

После этого вы будете иметь возможность ссылаться на заводскую сборку создать так:

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

Однако, есть одна проблема в вашем частный случай. По умолчанию разработчики FactoryGirl работают поверх интерфейса ActiveRecord. Она устанавливает атрибуты определённых через сеттер, а не через хэш ATTRS, переданную в модели конструктора:

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

Таким образом, вы должны создать пользовательский конструктор для работы с интерфейсом модели (которая не соответствует ActiveRecord -alike model) и зарегистрируйте его в своем заводском определении. См. factory girl docs.

Позвольте мне показать вам пример этого. К сожалению, я не проверял, но это должно дать вам подсказку:

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

Следует отметить, что только с FactoryGirl 2,5 имеет initialize_with поддержали: http://robots.thoughtbot.com/factory-girl-2-5-gets-custom-constructors (который только действительно имеет значение, если вам 're stuck using rspec 1.x из-за проблем с зависимостями) – Lambart

+0

Также обратите внимание: 'DEPRECATION WARNING: \' #ignore \ 'устарело и будет удалено в 5.0. Вместо этого используйте \ '#transient \'. – thisismydesign

0

Это потому, что у вас есть конструктор с обязательными аргументами. У вас есть несколько вариантов; !

1) Сделать аргумент необязательным (хотя это будет означать, что вы изменить свой код, чтобы удовлетворить ваши тесты - непослушные)

def initialize(message = nil) 

2) Используйте «initialize_with» синтаксис в вашем заводе;

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 
Смежные вопросы