Factory_bot में सरणी / हैश को कैसे परिभाषित करें?


80

मैं एक परीक्षण लिखने की कोशिश कर रहा हूं जो ड्रॉपबॉक्स की आरईएस सेवा से कुछ रिटर्न वैल्यू का अनुकरण करता है जो मुझे एक नेरेड हैश के साथ एरे में डेटा वापस देता है।

मुझे यह पता लगाने में कठिनाई हो रही है कि मेरे कारखाने को कैसे कोडित किया जाए क्योंकि रिटर्न रिजल्ट में एक के साथ एक सरणी है। यहाँ क्या जाएगा?

Factory.define :dropbox_hash do
 ??
end

ड्रॉपबॉक्स डेटा इस तरह दिखता है:

 ["/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)

क्या आपको वास्तव में इसके लिए किसी कारखाने की आवश्यकता है? सिर्फ एक विधि को परिभाषित क्यों न करें जो नकली प्रतिक्रिया देता है?
zetetic

यही मैंने खत्म किया। लेकिन मुझे लगा कि फैक्ट्रियों की बात इस सामान को अलग करने के लिए थी। मैं अभी भी उत्सुक हूँ - लगता है जैसे हैश और ऐरे कक्षाएं हैं और यह काम करना चाहिए अगर मुझे सिर्फ सही सिंटैक्स मिल सकता है।
डग

मैंने उन्हें केवल ActiveRecord मॉडल इंस्टेंसेस बनाने के लिए उपयोग किया है। FactoryGirl जुड़नार को बदलने का इरादा है। आप RSpec के सहायक तरीकों पर एक नज़र डाल सकते हैं: relishapp.com/rspec/rspec-core/v/2-9/docs/helper-methods
zetetic

जवाबों:


155

मैं एक ही काम करने में दिलचस्पी रखता था, मेरा एक मॉडल का परीक्षण करने के लिए जो एक 3-पार्टी एपीआई से सामग्री के हैश का उपयोग करके संचालित होता है। मैंने पाया कि 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 स्टोर को छोड़ देता है। इसलिए, हम कुछ भी जटिल बनाने के बजाय, अपनी सामग्री के रूप में पहले से तैयार विशेषता हैश को वापस कर देते हैं। वोइला।

वर्ग के लिए कुछ मूल्य निर्दिष्ट करना आवश्यक प्रतीत होता है, इसके बावजूद कि वास्तव में इसका उपयोग नहीं किया जा रहा है। यह फैक्ट्री_गर्ल को फैक्ट्री के नाम पर आधारित एक क्लास को इंस्टेंट करने की कोशिश से रोकने के लिए है। मैंने ऑब्जेक्ट के बजाय वर्णनात्मक कक्षाओं का उपयोग करने के लिए चुना है, लेकिन यह आपके ऊपर है।

जब आप इनमें से एक हैश कारखानों का उपयोग करते हैं, तब भी आप फ़ील्ड को ओवरराइड करने में सक्षम होते हैं:

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

.. जब भी, आपके पास नेस्टेड सामग्री है और गहरे क्षेत्रों को ओवरराइड करना चाहते हैं, तो आपको किसी प्रकार के गहरे मर्ज को करने के लिए इनिशियलाइज़ेशन ब्लॉक की जटिलता को बढ़ाना होगा।

आपके मामले में, आप कुछ मिश्रित सरणी और हैश डेटा का उपयोग कर रहे हैं, और ऐसा प्रतीत होता है कि पथ संरचना को डेटा संरचना के कुछ हिस्सों के बीच पुन: उपयोग किया जाना चाहिए। कोई समस्या नहीं है - आप सामग्री की संरचना को जानते हैं, इसलिए आप एक कारखाना बना सकते हैं जो परिणामस्वरूप सरणी को ठीक से बनाता है। यहाँ है कि मैं यह कैसे कर सकता हूँ:

  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)

आप अभी भी अनावश्यक मूल्यों को छोड़ने के लिए स्वतंत्र हैं। आइए केवल कल्पना करें कि पथ और रेव वास्तव में आवश्यक हैं:

  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)

यह एक बेहतरीन उपाय है। यहां तक ​​कि यह कारखानों की विरासत के साथ भी काम करता है।
डेविड पेलाज

यह मेरे लिए क्रिएशन / बिल्ड करने का काम करता है, लेकिन यह लिंट फेल करता है: FacoryGirl.lint
pixelearth

इसके लिए शुक्रिया। रुबोपॉप लिंटर को पास करने के लिए favoritesमल्टी लाइन ब्लॉक के उपयोग के do..endबजाय {{..}}
scarver2

आप skip_createकारखाने में जोड़ सकते हैं यदि आप build
साईराम

महान। मैंने पाया कि मैं किसी भी कस्टम क्लास को इनिशियलाइज़ कर सकता हूँ, initialize_withक्लास के संदर्भ में मूल्यांकन कर सकता हूँ , यानी अगर मेरे पास है initialize_with { new(attributes) }, तो build :my_factoryMyClass.new(attributes)
उसका

10

मेरे लिए यह काम कर रहा है, और मैं हैश में आवश्यकतानुसार विशेषताओं को पारित कर सकता हूं

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

3
यह कुंजी को तार होने की अनुमति देने का अतिरिक्त लाभ भी होगा।
crftr

यहाँ नकारात्मक पक्ष यह है कि आप एक ही वस्तु को संशोधित कर रहे हैं और हर बार नया नहीं बनाया जाता है। हैश के ऑब्जेक्ट_एड पर एक नज़र डालें
एंथनी

8

वर्तमान RSpec संस्करण के लिए एक अनुवर्ती (3.0):

बस अपने कारखाने को हमेशा की तरह परिभाषित करें और FactoryBot.attributes_forतात्कालिक वर्ग के बजाय हैश प्राप्त करने के लिए उपयोग करें।


2
मणि का नाम बदलकर FactoryBot कर दिया गया। उस दस्तावेज़ का नया स्थान rubydoc.info/github/thoughtbot/factory_bot/FactoryBot/Syntax/…
scarver2

6

आप 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
  • आपको एक ignoreब्लॉक का उपयोग करके सभी विशेषताओं को अनदेखा करने की आवश्यकता है ताकि यह उन्हें सरणी के बाद असाइन करने की कोशिश न करे, जैसेarray.revision = 48
  • आप इसे बता सकते हैं कि किस तरह से अपने रिजल्ट को एक साथ इस्तेमाल किया जा सकता है initialize_with । यहाँ नकारात्मक पक्ष यह है कि आपको पूरी विशेषता सूची फिर से लिखने की आवश्यकता है।
  • आपको एक खाली to_createब्लॉक प्रदान करने की आवश्यकता है ताकि वह array.save!बाद में कॉल करने का प्रयास न करे ।

0

मैंने OpenStruct का उपयोग किया:

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

संपादित करें: क्षमा करें, हैश के रूप में काम नहीं करता है

मैं अंत में एक स्थैतिक संस्करण का उपयोग करता हूं, बस उस हैश को फैक्ट्री सिस्टम से आने के लिए ...

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

कुछ बेहतर की तलाश है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.