J'essaie d'écrire un test qui simule certaines valeurs de retour du service REST de Dropbox qui me renvoie des données dans un tableau, avec un hachage imbriqué.
J'ai du mal à comprendre comment coder mon usine car le résultat de retour est un tableau avec un a à l'intérieur. Qu'est-ce qui irait ici?
Factory.define :dropbox_hash do
??
end
Les données de Dropbox ressemblent à ceci:
["/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"}]
Et je voudrais un appel d'usine comme celui-ci dans mon RSpec:
Factory.create(:dropbox_hash)
J'étais intéressé à faire la même chose, également pour tester un de mes modèles qui fonctionne en utilisant un hachage de contenu à partir d'une API tierce. J'ai découvert qu'en utilisant quelques-unes des fonctionnalités intégrées de factory_girl, j'ai pu construire proprement ce type de structures de données.
Voici un exemple artificiel:
factory :chicken, class:Hash do
name "Sebastian"
colors ["white", "orange"]
favorites {{
"PETC" => "http://www.petc.org"
}}
initialize_with { attributes }
end
L'astuce principale ici est que lorsque vous déclarez initialize_with, factory_girl ne tentera plus d'attribuer les attributs à l'objet résultant. Il semble également ignorer le magasin db dans ce cas. Ainsi, au lieu de construire quelque chose de compliqué, nous renvoyons simplement le hachage d'attribut déjà préparé comme notre contenu. Voila.
Il semble nécessaire de spécifier une valeur pour la classe, bien qu'elle ne soit pas réellement utilisée. C'est pour empêcher factory_girl d'essayer d'instancier une classe basée sur le nom de l'usine. J'ai choisi d'utiliser des classes descriptives plutôt que Object, mais c'est à vous.
Vous pouvez toujours remplacer les champs lorsque vous utilisez l'une de ces usines de hachage:
chick = FactoryGirl.build(:chicken, name:"Charles")
.. cependant, si vous avez du contenu imbriqué et que vous souhaitez remplacer des champs plus profonds, vous devrez augmenter la complexité du bloc d'initialisation pour effectuer une sorte de fusion profonde.
Dans votre cas, vous utilisez des données mixtes de tableau et de hachage, et il semble que la propriété Path devrait être réutilisée entre des parties de la structure de données. Pas de problème - vous connaissez la structure du contenu, vous pouvez donc facilement créer une fabrique qui construit correctement le tableau résultant. Voici comment je pourrais le faire:
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)
Vous êtes également toujours libre d'omettre des valeurs inutiles. Imaginons que seuls Path et rev soient vraiment nécessaires:
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)
a obtenu ce travail pour moi, et je peux passer des attributs au besoin dans le hachage
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" }
Un suivi pour la version actuelle de RSpec (3.0):
Définissez simplement votre usine comme d'habitude et utilisez FactoryBot.attributes_for
pour recevoir un hachage au lieu d'une classe instanciée.
Vous pouvez le faire dans les dernières versions de factory_girl, mais c'est gênant car il est conçu pour construire des objets et non des structures de données. Voici un exemple:
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
Revenant sur les trucs bizarres ici:
Object
ici pour l'empêcher de rechercher DropboxHash
.ignore
afin qu'il n'essaye pas de les affecter au tableau par la suite, comme array.revision = 48
.initialize_with
. L'inconvénient ici est que vous devez réécrire la liste complète des attributs.to_create
bloquer pour ne pas essayer d'appeler array.save!
ensuite.J'ai utilisé OpenStruct:
factory :factory_hash, class:OpenStruct do
foo "bar"
si "flar"
end
Modifier: désolé, ne fonctionne pas comme un hachage
J'utilise enfin une version statique, juste pour garder ce hachage provenant du système Factory ...
factory :factory_hash, class:Hash do
initialize_with { {
foo "bar"
si "flar"
} }
end
chercher quelque chose de mieux