80 votes

Comment définir un tableau / hachage dans Factory Girl?

J'essaie d'écrire un test qui simule certaines valeurs de retour du service REST de Dropbox qui me restitue les données d'un tableau, avec un hachage imbriqué.

Je ne parviens pas à comprendre comment coder mon usine car le résultat renvoyé est un tableau contenant un a. Qu'est-ce qui irait ici?

 Factory.define :dropbox_hash do
 ??
end
 

Les données 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 j'aimerais un appel d'usine comme celui-ci dans mon RSpec:

 Factory.create(:dropbox_hash)
 

161voto

doublemarked Points 760

J'ai été intéressé à faire la même chose, aussi de tester un modèle de la mienne qui fonctionne à l'aide d'un hachage du contenu à partir d'un 3e partie de l'API. J'ai trouvé qu'en utilisant quelques-uns des fonctionnalités intégrées de factory_girl j'ai pu proprement construire ce genre 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 ici est que, lorsque vous déclarez initialize_with, factory_girl ne tenteront plus d'affecter les attributs de la résultante de l'objet. Il semble également ignorer la db magasin dans ce cas. Donc, plutôt que de construire quelque chose de compliqué, nous venons de passer en arrière de la déjà préparé attribut de hachage que notre contenu. Le tour est joué.

Il ne semble pas nécessaire de spécifier une valeur pour le cours, en dépit de ce pas en réalité. C'est pour éviter d'factory_girl de tenter d'instancier une classe basée sur le nom de l'usine. J'ai choisi d'utiliser descriptif des classes plutôt que de l'Objet, mais c'est à vous.

Vous êtes toujours en mesure de remplacer les champs lorsque vous utilisez l'un de ces usines de hachage:

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

..cependant, si vous avez le contenu imbriqué et souhaitez remplacer les plus profondes des champs, vous devrez augmenter la complexité de l'initialisation du bloc pour faire une sorte de profondeur de fusion.

Dans votre cas, vous êtes en utilisant un mélange de tableau de hachage et de données, et il semble que le Chemin d'accès à la propriété devraient être réutilisé entre des parties de la structure de données. Pas de problème - vous connaître la structure du contenu, de sorte que vous pouvez facilement créer une usine qui construit le tableau résultant correctement. Voici comment je peut 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 libre de les omettre les valeurs inutiles. Imaginons un seul Chemin et rev sont 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)

11voto

jethroo Points 839

cela a fonctionné pour moi, et je peux transmettre les attributs nécessaires 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" }
 

8voto

ma_il Points 1903

Un suivi pour la version actuelle de RSpec (3.0):

Définissez simplement votre usine comme d’habitude et utilisez FactoryGirl.attributes_for pour recevoir un hachage au lieu d’une classe instanciée.

6voto

Joe Ferris Points 1135

Vous pouvez le faire dans les dernières versions de factory_girl, mais il est maladroit car il est conçu pour construire des objets et non pas 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

Aller sur le truc bizarre ici:

  • Chaque usine a besoin d'un valide construire en classe, même si elle n'est pas utilisée, donc je passe Object ici pour l'empêcher de recherche d' DropboxHash.
  • Vous devez ignorer tous les attributs à l'aide d'un ignore bloc de sorte qu'il ne tente pas de les attribuer à la matrice par la suite, comme array.revision = 48.
  • Vous pouvez dire comment mettre votre résultat à l'aide de initialize_with. L'inconvénient ici est que vous devez écrire l'intégralité de la liste des attributs de nouveau.
  • Vous devez fournir un vide to_create bloc de sorte qu'il ne tente pas d'appeler array.save! par la suite.

1voto

jobwat Points 1213

J'ai utilisé OpenStruct:

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

Edit: désolé, ne fonctionne pas comme un hachage

J'utilise finalement une version statique, juste pour que le hachage reste du système Factory ...

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

chercher quelque chose de mieux

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X