Как включить модуль в factory_girl factory?

#ruby-on-rails #module #mixins #factory-bot

#ruby-on-rails #модуль #миксины #factory-бот

Вопрос:

Я пытаюсь повторно использовать вспомогательный метод на всех своих фабриках, однако я не могу заставить его работать. Вот моя настройка:

Вспомогательный модуль (в spec / support/test_helpers.rb)

 module Tests
  module Helpers
    # not guaranteed to be unique, useful for generating passwords
    def random_string(length = 20)
      chars = ['A'..'Z', 'a'..'z', '0'..'9'].map{|r|r.to_a}.flatten
      (0...length).map{ chars[rand(chars.size)] }.join
    end
  end
end
  

Фабрика (в spec/factories/users.rb)

 FactoryGirl.define do
  factory :user do
    sequence(:username) { |n| "username-#{n}" }
    password random_string
    password_confirmation { |u| u.password }
  end
end
  

Если я запускаю свои тесты (с rake spec ), я получаю следующую ошибку везде, где я создаю пользователя с Factory(:user) :

  Failure/Error: Factory(:user)
 ArgumentError:
   Not registered: random_string
  

Что мне нужно сделать, чтобы иметь возможность использовать random_string на своих фабриках?

Я попробовал следующее:

  • использование include Tests::Helpers на каждом уровне моей фабрики (до define , между define и factory :user и внутри factory :user )
  • у spec_helper.rb меня уже есть следующее: config.include Tests::Helpers и это дает мне доступ к random_string моим спецификациям
  • просто требуется файл на моей фабрике

Я также безуспешно прочитал следующие ссылки:

Ответ №1:

Как насчет простого:

 module Tests
  module Helpers
    # not guaranteed to be unique, useful for generating passwords
    def self.random_string(length = 20)
      chars = ['A'..'Z', 'a'..'z', '0'..'9'].map{|r|r.to_a}.flatten
      (0...length).map{ chars[rand(chars.size)] }.join
    end
  end
end
  

Затем:

 FactoryGirl.define do
  factory :user do
    sequence(:username) { |n| "username-#{n}" }
    password Tests::Helpers.random_string
    password_confirmation { |u| u.password }
  end
end
  

Хорошо, понял 🙂 Выполните следующие действия:

 module FactoryGirl
  class DefinitionProxy
    def random_string
     #your code here
    end
  end
end
  

Комментарии:

1. Это работает так, но я надеялся, что мне не придется писать все пространство имен. Я оставлю вопрос открытым на случай, если кто-то найдет лучший способ.

2. Это работает, хотя я закончил, оставив свой вспомогательный модуль таким, какой он есть (с использованием метода экземпляра) и включив этот модуль в DefinitionProxy класс. Большое спасибо!

3. Важно отметить: мой rand метод не работал как есть, и мне пришлось заменить его Kernel.rand на из-за некоторого конфликта с FactoryGirl.

Ответ №2:

ответ apneadiving у меня не сработал. Я должен был сделать следующее:

 # /spec/support/factory_helpers.rb
module FactoryHelpers
  def my_helper_method
    # ...
  end
end

FactoryGirl::Proxy.send(:include, FactoryHelpers)
  

Затем вы можете использовать его следующим образом:

 FactoryGirl.define do
  factory :post do
    title { my_helper_method }
  end
end
  

Комментарии:

1. Выглядит намного проще, я попробую, когда у меня будет время.

2. FG v4 больше не использует ::Proxy — fwiw, вы получите тот же эффект, заменив FactoryGirl::Proxy.send в ответе @ FactoryGirl::SyntaxRunner.send cuvius на, но обратите внимание, что разработчик gem думает о правильном решении в самом gem , поэтому следите за этими событиями, если вы делаете это.

Ответ №3:

Вчера я тестировал другие ответы (24.04.2012) и … ни один из них на самом деле не работает.

Похоже, что Factory Girl gem (v3.2.0) сильно изменился.

Но я нашел быстрое решение:

 # factories.rb
module FactoryMacros
  def self.create_file(path)
    file = File.new(path)
    file.rewind
    return ActionDispatch::Http::UploadedFile.new(:tempfile => file,
                                            :filename => File.basename(file))
  end
end
# also factories.rb
FactoryGirl.define do

  factory :thing do |t|
    t.file { FactoryMacros::create_file("path-to-file")
  end
end