2013-07-31 3 views
11

Modelle/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 

spec/models/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

Failures:Fabrik Mädchen Argumente auf Build zu modellieren Definition vorbei/erstellen

1) Meldung sollte die Nutzlast speichern

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

Antwort

17

factory erfordert, dass Sie Fabrik zunächst definieren. Sagen wir, in einer Datei spec/Fabriken/messages.rb:

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

Danach Sie in der Lage sein werden Fabrik bauen erstellen wie folgt aufzurufen:

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

Allerdings gibt es ein Problem in Ihrem spezieller Fall. Die Standard-Builder von FactoryGirl arbeiten auf einer ActiveRecord-ähnlichen Oberfläche. Es setzt definierte Attribute durch Einrichter, nicht durch einen Hash von attrs zum Modell Konstruktor übergeben:

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

So haben Sie einen benutzerdefinierten Konstruktor erstellen mit der Schnittstelle Ihres Modells zu arbeiten (was nicht zu Active nicht entspricht -Alike-Modell) und registrieren Sie es in Ihrer Fabrikdefinition. Siehe factory girl docs für weitere Einzelheiten.

Lassen Sie mich Ihnen ein Beispiel, dies zu tun. Leider habe ich es nicht getestet, aber es sollte Ihnen einen Hinweis geben:

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

Es sei darauf hingewiesen nur werden sollte, dass seit 2.5 factory hat initialize_with unterstützt: http://robots.thoughtbot.com/factory-girl-2-5-gets-custom-constructors (die eigentlich nur, wenn Sie es ankommt bist stecken mit rspec 1.x aufgrund Abhängigkeitsprobleme) – Lambart

+0

beachten Sie auch: 'deprecation ACHTUNG: \' #ignore \ 'veraltet und wird in 5.0 entfernt werden. Bitte verwenden Sie stattdessen '' transient \ '' – thisismydesign

0

Es ist, weil Sie einen Konstruktor mit obligatorischen Argumente haben. Sie haben ein paar Optionen; !

1) Stellen Sie das Argument nicht zwingend (auch wenn dies bedeuten würde Sie Ihren Code sind, wenn Sie Ihre Tests entsprechen - unartig)

def initialize(message = nil) 

2) Verwenden Sie die "initialize_with" Syntax in Ihrer Fabrik;

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 
Verwandte Themen