Rails 和 MiniTest:如何为 app/lib/mymodule 中的内容编写测试(Class 未找到)?
Rails and MiniTest: How to write tests for something in app/lib/mymodule (Class not found)?
Rails 5.2 这里。
我想测试在 app/lib/legacy/export.rb
:
中定义的 class
# app/lib/legacy/export.rb
module Legacy
class Export
def initialize ; end
end
end
但是,test/services/legacy_export_test.rb
中的测试
# test/services/legacy_export_test.rb
require 'test_helper'
class LegacyExportTest < ActiveSupport::TestCase
test 'can be initialized' do
Legacy::Export.new
end
end
会吐NameError: uninitialized constant Legacy::Export
.
如果我将 class 定义放在 app/lib/export.rb
中(并删除 module
定义),效果会很好。
我还可以在控制器和 rails 控制台 (rails c
) 中引用此 class。
尝试从顶级 "namespace" (::Legacy::Export
) 开始引用 class 也无济于事。我找到了有关如何在 test/
文件夹中引用 lib
文件夹(和子目录)的问题的答案,但这不是我需要的。
require 'lib/legacy/export
会告诉我 cannot load such file
,require 'legacy/export'
.
也会
我假设 Rails 和 MiniTest 的(自动)加载内容是相同的,但显然还有一些额外的配置需要完成。
必须做什么?我在哪里可以找到这些信息?
问题是您的 class 命名空间/class 路径与 Rails autoloading 开箱即用的方式不匹配。
当您使用之前未声明的 class 时,默认情况下 Rails 将查找特定路径(在 config.autoload_paths
上定义)
- app/controllers
- app/controllers/关注
- app/models
- app/models/关注
- ...
当你第一次使用 User
时,因为它(还)没有定义,它会循环遍历这些路径并尝试要求 app/controllers/user.rb, app/controllers/concerns/user.rb, app/models/user.rb, 直到找到 User
class
如果您的 class 命名空间为 Legacy::Export,那么它将查找 app/models/legacy/export.rb、app/models/concerns/legacy/ export.rb、app/controllers/legacy/export.rb 等
这就是它找不到您的 class 的原因:您的文件位于 app/lib
,不在 Rails 用于查找的路径内。
有不同的解决方案:
选项#1
明确要求文件。 (Ruby 方式)
require_relative '../../app/lib/legacy/export'
选项#2
将 app/lib
添加到 autoload_path
(在 config/application.rb
中)
(Rails 方式)
module YourApp
class Application < Rails::Application
# ...
config.autoload_paths << Rails.root.join("app/lib")
end
end
选项#3
调整命名空间以匹配自动加载的预期(而不是更改配置)
示例:将您的文件移动到类似 app/models/legacy/export.rb
的位置
Rails 5.2 这里。
我想测试在 app/lib/legacy/export.rb
:
# app/lib/legacy/export.rb
module Legacy
class Export
def initialize ; end
end
end
但是,test/services/legacy_export_test.rb
# test/services/legacy_export_test.rb
require 'test_helper'
class LegacyExportTest < ActiveSupport::TestCase
test 'can be initialized' do
Legacy::Export.new
end
end
会吐NameError: uninitialized constant Legacy::Export
.
如果我将 class 定义放在 app/lib/export.rb
中(并删除 module
定义),效果会很好。
我还可以在控制器和 rails 控制台 (rails c
) 中引用此 class。
尝试从顶级 "namespace" (::Legacy::Export
) 开始引用 class 也无济于事。我找到了有关如何在 test/
文件夹中引用 lib
文件夹(和子目录)的问题的答案,但这不是我需要的。
require 'lib/legacy/export
会告诉我 cannot load such file
,require 'legacy/export'
.
我假设 Rails 和 MiniTest 的(自动)加载内容是相同的,但显然还有一些额外的配置需要完成。
必须做什么?我在哪里可以找到这些信息?
问题是您的 class 命名空间/class 路径与 Rails autoloading 开箱即用的方式不匹配。
当您使用之前未声明的 class 时,默认情况下 Rails 将查找特定路径(在 config.autoload_paths
上定义)
- app/controllers
- app/controllers/关注
- app/models
- app/models/关注
- ...
当你第一次使用 User
时,因为它(还)没有定义,它会循环遍历这些路径并尝试要求 app/controllers/user.rb, app/controllers/concerns/user.rb, app/models/user.rb, 直到找到 User
class
如果您的 class 命名空间为 Legacy::Export,那么它将查找 app/models/legacy/export.rb、app/models/concerns/legacy/ export.rb、app/controllers/legacy/export.rb 等
这就是它找不到您的 class 的原因:您的文件位于 app/lib
,不在 Rails 用于查找的路径内。
有不同的解决方案:
选项#1
明确要求文件。 (Ruby 方式)
require_relative '../../app/lib/legacy/export'
选项#2
将 app/lib
添加到 autoload_path
(在 config/application.rb
中)
(Rails 方式)
module YourApp
class Application < Rails::Application
# ...
config.autoload_paths << Rails.root.join("app/lib")
end
end
选项#3
调整命名空间以匹配自动加载的预期(而不是更改配置)
示例:将您的文件移动到类似 app/models/legacy/export.rb