我如何分享我在创业板上的工厂并在其他项目中使用它?

Eki*_*bal 15 ruby gem rspec ruby-on-rails factory-bot

我有一个包含一些工厂的宝石.宝石看起来像:

.
??? Gemfile
??? Gemfile.lock
??? README.md
??? Rakefile
??? db
??? lib
?   ??? models
?   ?   ??? users.rb
??? pkg
??? core.gemspec
??? spec
?   ??? factories
?   ?   ??? users.rb
?   ??? fixtures
?   ??? helpers
?   ??? integration
?   ??? spec_helper.rb
?   ??? support?   ? 
?   ??? unit
?       ??? users_spec.rb
??? tasks
Run Code Online (Sandbox Code Playgroud)

现在我通过添加类似的东西在另一个Ruby项目(Grape)中使用gem gem 'core', git: 'https://url.git'.

现在一切正常,因为我可以使用UserGrape项目的模型.

但是我想使用工厂(users),所以我可以为Grape项目编写进一步的集成测试.

在Grape项目中,spec_helper.rb它看起来像:

require 'rubygems'
require 'bundler/setup'
Bundler.require(:default, :development)

ENV['RACK_ENV'] ||= 'test'

require 'rack/test'

require File.expand_path('../../config/environment', __FILE__)

RSpec.configure do |config|
  config.mock_with :rspec
  config.expect_with :rspec
  config.raise_errors_for_deprecations!
  config.include FactoryGirl::Syntax::Methods
end

require 'capybara/rspec'
Capybara.configure do |config|
  config.app = Test::App.new
  config.server_port = 9293
end
Run Code Online (Sandbox Code Playgroud)

现在我的测试'users_spec.rb'看起来像:

require 'spec_helper'

describe App::UsersController do
  include Rack::Test::Methods

  def app
    App::API
  end

  describe "/users/me" do
    context "with invalid access token" do
      before(:each) do
        get "/api/v2/users/me"
        user = build(:user)
      end      

      it 'returns 401 error code' do
        expect(last_response.status).to eq(401)
        expect(user).to eq(nil)
      end
    end    
  end
end
Run Code Online (Sandbox Code Playgroud)

现在,当我尝试运行测试时,rspec spec/api/users_spec.rb我得到:

我一直收到这个错误:

 Failure/Error: user = build(:user)
 ArgumentError:
   Factory not registered: user
Run Code Online (Sandbox Code Playgroud)

任何帮助都会受到赞赏,因为我一直在努力争取这个.

Rng*_*Tng 12

问题是您可能不会在加载路径中公开spec文件夹(以及工厂).一般来说,这是正确的做法.检查您*.gemspec,你可能有类似的东西:

s.require_paths = ["lib"]
Run Code Online (Sandbox Code Playgroud)

这意味着只有lib使用gem的其他项目才能要求目录下的文件.请参阅http://guides.rubygems.org/specification-reference/#require_paths=

因此,要解决您的问题,您需要将文件放在lib"知道"工厂所在的文件夹中,并且需要这些文件.所以在你的情况下,创建一个文件lib/<your gem name>/factories.rb并添加:

GEM_ROOT = File.dirname(File.dirname(File.dirname(__FILE__)))

Dir[File.join(GEM_ROOT, 'spec', 'factories', '*.rb')].each { |file| require(file) }
Run Code Online (Sandbox Code Playgroud)

在另一个项目中加载工厂:

require '<your gem name>/factories'

对我来说很好.我唯一没想到的是如何命名你的工厂.不确定工厂女孩是否允许这样做.

  • `Dir [File.join(GEM_ROOT,'spec','factories','**','*.rb')].每个{| file | require(file)}`这将包括子文件夹中的工厂 (3认同)

odl*_*dlp 7

require另一个答案中建议的 -ing 每个工厂文件的替代方法是更新FactoryBot.definition_file_paths配置。

在定义工厂的 gem 中:

创建一个文件来解析工厂路径:

# lib/my_gem/test_support.rb

module MyGem
  module TestSupport
    FACTORY_PATH = File.expand_path("../../spec/factories", __dir__)
  end
end
Run Code Online (Sandbox Code Playgroud)

在你的 app/gem 中使用其他 gem 的工厂:

# spec/spec_helper.rb or similar

require "my_gem/test_support"

FactoryBot.definition_file_paths = [
  MyGem::TestSupport::FACTORY_PATH,
  # Any other paths you want to add e.g.
  # Rails.root.join("spec", "factories")
]

FactoryBot.find_definitions
Run Code Online (Sandbox Code Playgroud)

definition_file_paths解决方案的优点是其他功能如FactoryBot.reload预期的那样工作。