工厂女孩传递参数建模/创建模型定义

时间:2013-07-31 10:30:33

标签: ruby-on-rails ruby factory-bot rspec-rails

模型/ 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)>'

2 个答案:

答案 0 :(得分:21)

FactoryGirl要求您先定义工厂。让我们说文件spec / factories / 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相似的界面上运行。它通过setter设置定义的属性,而不是通过传递给模型构造函数的attrs散列:

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

因此,您必须创建一个自定义构造函数来处理模型的接口(不符合类似ActiveRecord的模型)并在工厂定义中注册它。有关详细信息,请参阅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

答案 1 :(得分: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