Factory девушка, передающая аргументы в определение модели для сборки/создания
модели /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)>'
Ответы
Ответ 1
FactoryGirl требует сначала определить factory. Скажем, в файле spec/factory/messages.rb:
FactoryGirl.define do
factory :message do
bundle_id 1
order_id 2
...etc...
end
end
После этого вы сможете вызвать factory build create следующим образом:
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-like) и зарегистрировать ее в определении factory. Подробнее см. factory docs 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
Ответ 2
Это потому, что у вас есть конструктор с обязательными аргументами. У вас есть несколько вариантов:
1) Сделайте аргумент не обязательным (хотя это будет означать, что вы меняете свой код в соответствии с вашими испытаниями - озорной!)
def initialize(message = nil)
2) Используйте синтаксис "initialize_with" в factory;
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