web-dev-qa-db-ja.com

Factory Girlで配列/ハッシュを定義する方法は?

DropboxのRESTサービスからの戻り値をシミュレートするテストを作成しようとしています。このサービスは、ネストされたハッシュを使用して、配列にデータを返します。

返される結果は内部の配列であるため、ファクトリのコーディング方法を理解するのに苦労しています。ここに何が行きますか?

Factory.define :dropbox_hash do
 ??
end

Dropboxデータは次のようになります。

 ["/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"}] 

そして、私は私のRSpecでこのようなファクトリーコールが欲しいです:

Factory.create(:dropbox_hash)
77
Doug

同じことをすることに興味があり、サードパーティAPIのコンテンツのハッシュを使用して動作する私のモデルをテストすることにも興味がありました。 factory_girlの組み込み機能をいくつか使用することで、この種のデータ構造をきれいに構築できることがわかりました。

これが不自然な例です:

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

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

    initialize_with { attributes } 
  end

ここでの主なトリックは、initialize_withを宣言すると、factory_girlが結果のオブジェクトに属性を割り当てようとしないことです。この場合、dbストアもスキップするようです。したがって、複雑なものを作成する代わりに、すでに準備された属性ハッシュをコンテンツとして返すだけです。出来上がり。

実際には使用されていませんが、クラスに値を指定する必要があるようです。これは、factory_girlがファクトリ名に基づいてクラスをインスタンス化しようとするのを防ぐためです。オブジェクトではなく記述クラスを使用することを選択しましたが、それはあなた次第です。

これらのハッシュファクトリのいずれかを使用する場合、引き続きフィールドをオーバーライドできます。

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

..ただし、ネストされたコンテンツがあり、より深いフィールドをオーバーライドする場合は、初期化ブロックの複雑さを増して、何らかの深いマージを行う必要があります。

あなたのケースでは、配列とハッシュの混合データを使用しているため、データ構造の部分間でPathプロパティを再利用する必要があるようです。問題ありません-コンテンツの構造がわかっているので、結果の配列を適切に構築するファクトリを簡単に作成できます。以下がその方法です。

  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)

不要な値を省略することもできます。 Pathとrevのみが本当に必要だと想像してみましょう:

  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)
143
doublemarked

これは私のために働いており、必要に応じてハッシュに属性を渡すことができます

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" }
8
jethroo

現在のRSpecバージョン(3.0)のフォローアップ:

通常どおりファクトリを定義し、 FactoryBot.attributes_for インスタンス化されたクラスの代わりにハッシュを受け取ります。

7
milgner

Factory_girlの最新バージョンでこれを行うことができますが、データ構造ではなくオブジェクトを構築するように設計されているため、厄介です。次に例を示します。

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

ここで奇妙なものを調べます:

  • すべてのファクトリは、使用されていない場合でも有効なビルドクラスを必要とするため、Objectを探しないようにここにDropboxHashを渡しました。
  • array.revision = 48のように、後で配列に割り当てようとしないように、ignoreブロックを使用してすべての属性を無視する必要があります。
  • initialize_withを使用して、結果をまとめる方法を伝えることができます。ここでの欠点は、完全な属性リストを再度書き出す必要があることです。
  • 空のto_createブロックを提供して、後でarray.save!を呼び出そうとしないようにする必要があります。
5
Joe Ferris

OpenStructを使用しました。

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

編集:申し訳ありませんが、ハッシュとしては機能しません

Factoryシステムからのハッシュを維持するためだけに、最終的に静的バージョンを使用します...

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

より良いものを探している

0
jobwat