如何共享我在 GEM 中拥有的工厂并在其他项目中使用它?
How can I share the factories that I have in a GEM and use it in other project?
我有一个 gem,其中包括一些工厂。 gem 看起来像:
.
├── 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
现在我在另一个 Ruby 项目 (Grape) 中使用 gem,方法是添加 gem 'core', git: 'https://url.git'
之类的东西。
现在一切正常,因为我可以使用来自 Grape 项目的 User
模型。
不过我想使用工厂 (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
现在我的测试 '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
现在,当我尝试 运行 使用 rspec spec/api/users_spec.rb
进行测试时,我得到:
我不断收到此错误:
Failure/Error: user = build(:user)
ArgumentError:
Factory not registered: user
任何帮助将不胜感激,因为我一直在为此努力。
问题是您可能没有在加载路径中公开 spec 文件夹(以及工厂)。一般来说,这是正确的做法。检查你 *.gemspec
,你可能有这样的东西:
s.require_paths = ["lib"]
这意味着使用您的 gem 的其他项目只能需要 lib
目录下的文件。参见 http://guides.rubygems.org/specification-reference/#require_paths=
因此,要解决您的问题,您需要在 lib
文件夹中放置一个文件,'knowns' 您的工厂所在的文件夹需要这些文件夹。所以在你的情况下,创建一个文件 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) }
在另一个项目中加载工厂:
require '<your gem name>/factories'
对我来说很好用。我唯一还没有弄清楚的是如何命名你的工厂。不确定工厂女孩是否允许这样做。
另一个答案中建议的 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
在您的应用程序中/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
definition_file_paths
解决方案的优势在于 FactoryBot.reload
等其他功能将按预期工作。
我有一个 gem,其中包括一些工厂。 gem 看起来像:
.
├── 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
现在我在另一个 Ruby 项目 (Grape) 中使用 gem,方法是添加 gem 'core', git: 'https://url.git'
之类的东西。
现在一切正常,因为我可以使用来自 Grape 项目的 User
模型。
不过我想使用工厂 (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
现在我的测试 '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
现在,当我尝试 运行 使用 rspec spec/api/users_spec.rb
进行测试时,我得到:
我不断收到此错误:
Failure/Error: user = build(:user)
ArgumentError:
Factory not registered: user
任何帮助将不胜感激,因为我一直在为此努力。
问题是您可能没有在加载路径中公开 spec 文件夹(以及工厂)。一般来说,这是正确的做法。检查你 *.gemspec
,你可能有这样的东西:
s.require_paths = ["lib"]
这意味着使用您的 gem 的其他项目只能需要 lib
目录下的文件。参见 http://guides.rubygems.org/specification-reference/#require_paths=
因此,要解决您的问题,您需要在 lib
文件夹中放置一个文件,'knowns' 您的工厂所在的文件夹需要这些文件夹。所以在你的情况下,创建一个文件 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) }
在另一个项目中加载工厂:
require '<your gem name>/factories'
对我来说很好用。我唯一还没有弄清楚的是如何命名你的工厂。不确定工厂女孩是否允许这样做。
另一个答案中建议的 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
在您的应用程序中/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
definition_file_paths
解决方案的优势在于 FactoryBot.reload
等其他功能将按预期工作。