2012-04-05 10 views
64

Sto provando a scrivere un test che simula alcuni valori di ritorno dal servizio REST di Dropbox che mi restituisce i dati in una matrice, con un hash annidato.Come definire un array/hash in Factory Girl?

Ho difficoltà a capire come codificare la mia Factory poiché il risultato di ritorno è un array con un has dentro. Cosa andrebbe qui?

Factory.define :dropbox_hash do 
?? 
end 

Dropbox dati assomiglia a questo:

["/home", {"revision"=>48, "rev"=>"30054214dc", "thumb_exists"=>false, "bytes"=>0, "modified"=>"Thu, 29 Dec 2011 01:53:26 +0000", "path"=>"/Home", "is_dir"=>true, "icon"=>"folder_app", "root"=>"app_folder", "size"=>"0 bytes"}] 

e vorrei una chiamata fabbrica come questo nel mio RSpec:

Factory.create(:dropbox_hash) 
+0

Avete veramente bisogno di una fabbrica per questo? Perché non basta definire un metodo che restituisce la risposta simulata? – zetetic

+0

Questo è quello che ho finito per fare. Ma pensavo che il punto delle Fabbriche fosse isolare questa roba. Sono ancora curioso: sembra che Hash e Array siano classi e questo dovrebbe funzionare se riesco a trovare la sintassi giusta. – Doug

+0

Li ho usati solo per generare istanze di modelli ActiveRecord. FactoryGirl è destinato a sostituire i dispositivi. Potresti dare un'occhiata ai metodi di supporto di RSpec: https://www.relishapp.com/rspec/rspec-core/v/2-9/docs/helper-methods – zetetic

risposta

125

Mi interessava fare la stessa cosa, anche per testare un mio modello che funziona usando un hash di contenuto da un'API di terze parti. Ho scoperto che, utilizzando alcune delle funzionalità integrate di factory_girl, ero in grado di costruire in modo pulito questo tipo di strutture di dati.

Ecco un esempio inventato:

factory :chicken, class:Hash do 
    name "Sebastian" 
    colors ["white", "orange"] 

    favorites {{ 
     "PETC" => "http://www.petc.org" 
    }} 

    initialize_with { attributes } 
    end 

Il trucco principale è che quando si dichiara initialize_with, factory_girl non sarà più tenterà di assegnare gli attributi per l'oggetto risultante. Sembra anche saltare l'archivio db in questo caso. Quindi, invece di costruire qualcosa di complicato, passiamo semplicemente l'hash dell'attributo già preparato come contenuto. Ecco.

Sembra necessario specificare un valore per la classe, nonostante non sia effettivamente utilizzato. Questo per impedire a factory_girl di tentare di istanziare una classe in base al nome della fabbrica. Ho scelto di utilizzare classi descrittive piuttosto che Object, ma dipende da te.

Sei ancora in grado di sostituire i campi quando si utilizza uno di questi stabilimenti hash:

chick = FactoryGirl.build(:chicken, name:"Charles") 

..however, contenuto se hai nidificato e vuole sovrascrivere i campi più profondi è necessario aumentare la complessità del blocco di inizializzazione per fare una sorta di fusione profonda.

Nel tuo caso, stai utilizzando dati misti di array e hash e sembra che la proprietà Path debba essere riutilizzata tra porzioni della struttura dati. Nessun problema: conosci la struttura del contenuto, quindi puoi creare facilmente una factory che costruisca correttamente la matrice risultante. Ecco come potrei farlo:

factory :dropbox_hash, class:Array do 
    path "/home" 
    revision 48 
    rev "30054214dc" 
    thumb_exists false 
    bytes 0 
    modified { 3.days.ago } 
    is_dir true 
    icon "folder_app" 
    root "app_folder" 
    size "0 bytes" 

    initialize_with { [ attributes[:path], attributes ] } 
    end 

    FactoryGirl.build(:dropbox_hash, path:"/Chickens", is_dir:false) 

Sei anche libero di omettere valori non necessari. Immaginiamo unica strada e il contagiri sono realmente necessari:

factory :dropbox_hash, class:Array do 
    path "/home" 
    rev "30054214dc" 
    initialize_with { [ attributes[:path], attributes ] } 
    end 

    FactoryGirl.build(:dropbox_hash, path:"/Chickens", revision:99, modified:Time.now) 
+0

Questa è un'ottima soluzione. Funziona anche con l'ereditarietà delle fabbriche. –

4

Si può fare questo nelle ultime versioni di factory_girl, ma è scomodo perché è progettato per costruire oggetti e non strutture dati. Ecco un esempio:

FactoryGirl.define do 
    factory :dropbox_hash, :class => 'Object' do 
    ignore do 
     url { "/home" } 
     revision { 48 } 
     rev { "30054214dc" } 
     # more attributes 
    end 
    initialize_with { [url, { "revision" => revision, "rev" => rev, ... }] } 
    to_create {} 
    end 
end 

Andando oltre la roba strana qui:

  • Ogni fabbrica ha bisogno di una classe di build valida anche se non è usato, così ho passato Object qui per evitare che si cerca di DropboxHash.
  • È necessario ignorare tutti gli attributi utilizzando un blocco ignore in modo che non tenti di assegnarli successivamente all'array, ad esempio array.revision = 48.
  • Puoi dire come mettere insieme il risultato usando initialize_with. Il rovescio della medaglia qui è che è necessario scrivere di nuovo l'elenco completo degli attributi.
  • È necessario fornire un blocco to_create vuoto in modo che non tenti di chiamare in seguito array.save!.
-1

ho usato OpenStruct:

factory :factory_hash, class:OpenStruct do 
    foo "bar" 
    si "flar" 
end 

Edit: mi dispiace, non funziona come un Hash

ho finalmente utilizzare una versione statica, solo per mantenere l'hash proveniente dal sistema Factory ...

factory :factory_hash, class:Hash do 
    initialize_with { { 
    foo "bar" 
    si "flar" 
    } } 
end 

cercare qualcosa di meglio

6

un follow-up per la versione attuale RSpec (3.0):

Basta definire la vostra fabbrica come al solito e utilizzare FactoryGirl.attributes_for di ricevere un hash invece di una classe di un'istanza.

4

ottenuto questo lavoro per me, e posso passare gli attributi come necessario nella hash

factory :some_name, class:Hash do 
    defaults = { 
    foo: "bar", 
    baz: "baff" 
    } 
    initialize_with{ defaults.merge(attributes) } 
end 

> build :some_name, foo: "foobar" #will give you 
> { foo: "foobar", baz: "baff" } 
+1

Ciò avrà anche il vantaggio di consentire alle chiavi di essere stringhe. – crftr

Problemi correlati