我正在使用Cucumber和capybara-webkit进行我的应用程序在Ruby 2.0.0,Rails 4.1上的集成测试。在我的黄瓜测试套件中进行了一些测试,意外地开始吐出这样的错误:
Circular dependency detected while autoloading constant UiValidators::ParameterFinder (RuntimeError)
/Users/kingp/.rvm/gems/ruby-2.0.0-p451@triquest/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:484:in `load_missing_constant'
/Users/kingp/.rvm/gems/ruby-2.0.0-p451@triquest/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:180:in `const_missing'
/Users/kingp/Projects/rails-triquest/app/controllers/contacts_controller.rb:2:in `<class:ContactsController>'
/Users/kingp/Projects/rails-triquest/app/controllers/contacts_controller.rb:1:in `<top (required)>'
/Users/kingp/.rvm/gems/ruby-2.0.0-p451@triquest/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:247:in `require'
...
错误显示'循环依赖',但实际上它是在Rails自动加载器尝试加载已经在其加载常量集中的常量时抛出的。通常这确实是由于循环依赖,但我很确定在我的应用程序中并非如此。分支与崩溃测试和我分支的稳定分支之间的差异表明,唯一的变化是coffeescript文件,视图模板,迁移和我正在编写的新黄瓜功能。我没有触及任何控制器或型号代码。
我最终在rails自动加载器中插入了一些日志代码,以帮助我弄清楚发生了什么:
# Inserted at activesupport-4.1.1/lib/active_support/dependencies.rb:467
_thread_id_for_debug = Thread.current.object_id
STDERR.puts "*** #{loaded.count} #{from_mod} #{const_name} - #{_thread_id_for_debug}"
loaded
是自动加载代码文件的一组路径,from_mod
请求来自的上下文,const_name
我们尝试加载的常量。在撞车事故发生之前,所有这些最终让我得到了这个:
*** 104 Object SitesController - 70180261360940
*** 105 Object ContactsController - 70180240113760
*** 105 SitesController UiValidators - 70180261360940
*** 105 Object UiValidators - 70180261360940
*** 105 UiValidators ParameterFinder - 70180261360940
*** 107 UiValidators ParameterFinder - 70180240113760
看起来两个线程正试图自动加载相同的常量。我的猜测是,在第一个线程完成加载之前,常量的名称被添加到Rails的'加载'常量集中。第二个线程无法解析常量(因为负载尚未完成),要求自动加载器找到它,并且当自动加载器在其“加载”集中看到常量时引发自动加载器。
在测试的这一点上,两个控制器(SitesController和ContactsController)正在响应几乎同时启动的AJAX请求。
我找到了解决崩溃的方法,只需在AJAX之前包含对模块UiValidators::ParameterFinder
的引用。但这似乎很脆弱,也不是很优雅。如果没有打开测试环境的急切加载,还有其他方法可以避免这个问题吗?
答案 0 :(得分:0)
我遇到了同样的问题(没有Cucumber,只有Capybara&amp; Poltergeist)。设置config.eager_load = true
甚至不能为我工作(不太明白为什么不......)。
我最终使用Spring并且自那以来没有出现循环依赖性错误。
答案 1 :(得分:0)
使用Sidekiq时,我在Rails 4.1.4中遇到了同样的问题。我假设在调用 active_support 中的const_missing
时,线程Sidekiq工作人员内部的竞争条件导致了各种各样的障碍。
除了确保我当前的环境会执行急切加载,即通过config.eager_load = true
我还必须将我的工作人员正在使用的所有组件从lib
目录添加到config.eager_load_paths
(通过config.eager_load_paths += %W(#{config.root}/lib)
内的config/application.rb
。
这是必要的,因为我假设设置config.eager_load = true
只会让Rails急切加载app/
目录的内容。
App::Application.config.eager_load_paths
=> [
[0] "/home/archive/releases/20140721180504/app/assets",
[1] "/home/archive/releases/20140721180504/app/controllers",
[2] "/home/archive/releases/20140721180504/app/helpers",
[3] "/home/archive/releases/20140721180504/app/mailers",
[4] "/home/archive/releases/20140721180504/app/models",
[5] "/home/archive/releases/20140721180504/app/services",
[6] "/home/archive/releases/20140721180504/app/workers"
]
两者的结合似乎有助于解决这个问题。