【问题标题】:Rails : RuntimeError - can't modify frozen Array when running rspec in railsRails:RuntimeError - 在 rails 中运行 rspec 时无法修改冻结的数组
【发布时间】:2017-11-16 02:52:17
【问题描述】:

我最近从 v4.3 升级到 Rails 5.1,现在在运行测试时遇到此错误:

An error occurred while loading 

./spec/controllers/admin/capacity_charges_controller_spec.rb.
Failure/Error: require File.expand_path('../../config/environment', __FILE__)

RuntimeError:
  can't modify frozen Array

我为每个测试文件获取它。触发错误的行来自 rails_helper。我检查了 rails 5.1 sample repos,我们的版本没有什么大的不同。

完整的堆栈跟踪是:

RuntimeError:


can't modify frozen Array
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/actionpack-5.1.0/lib/action_dispatch/middleware/stack.rb:74:in `insert'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/actionpack-5.1.0/lib/action_dispatch/middleware/stack.rb:74:in `insert'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/actionpack-5.1.0/lib/action_dispatch/middleware/stack.rb:81:in `insert_after'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/request_store-1.3.2/lib/request_store/railtie.rb:5:in `block in <class:Railtie>'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/railties-5.1.0/lib/rails/initializable.rb:30:in `instance_exec'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/railties-5.1.0/lib/rails/initializable.rb:30:in `run'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/railties-5.1.0/lib/rails/initializable.rb:59:in `block in run_initializers'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/railties-5.1.0/lib/rails/initializable.rb:58:in `run_initializers'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/railties-5.1.0/lib/rails/application.rb:353:in `initialize!'
# ./config/environment.rb:5:in `<top (required)>'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `require'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `block in require'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:258:in `load_dependency'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `require'
# ./spec/rails_helper.rb:12:in `<top (required)>'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `require'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `block in require'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:258:in `load_dependency'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:292:in `require'
# ./spec/controllers/admin/capacity_charges_controller_spec.rb:3:in `<top (required)>'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:286:in `load'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:286:in `block in load'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:258:in `load_dependency'
# /Users/jeremynagel/.rvm/gems/ruby-2.3.1@Rails4.2_EnergyLink/gems/activesupport-5.1.0/lib/active_support/dependencies.rb:286:in `load'

【问题讨论】:

    标签: ruby-on-rails ruby rspec


    【解决方案1】:

    原来这是由堆栈跟踪中较高的测试失败引起的。很难看出根本原因是什么,因为控制台中有太多内容。如果您遇到此问题,我建议您使用--fail-fast,这样您就不会被反复出现的错误消息淹没。然后检查第一个错误是什么。

    【讨论】:

    • pg 连接在我的情况下:)
    • 我的 factory_bot 规范中有一个重复的工厂生成器名称,导致了这种情况
    • 我有一个文件 foo/bar.rb 在我的例子中没有定义常量 Foo::Bar。这仅在激活急切加载时失败。
    • 是的,这个错误太可怕了。每次我在某处搞砸重命名文件或重命名require path 时都会收到此错误。然后祝你好运,在我的数百个文件中找到这个单字母拼写错误。
    • --fail-fast 不起作用,但将输出传送到 more 工作正常。原来我的 FactoryBot 文件中有一些重复的特征。
    【解决方案2】:

    对我来说,这是一个 FactoryBot 从版本 45 的更新。我没有看到弃用警告,因为我跳转了版本:

    DEPRECATION WARNING: Static attributes will be removed in FactoryBot 5.0.
    

    【讨论】:

    • 这对我也有用,在 /spec/factories 中将 last_name "Lincoln" 更改为 last_name { "Lincoln" } 解决了冻结数组错误
    【解决方案3】:

    有时,如果您在 Ruby 类中继承了错误的类名,也会引发此异常。请记住,控制器、模型等在 Ruby 中都是常量。

    这是我遇到的情况的一个例子。实际语法可能不正确,但这是导致我的问题的概念。

    module Admin
      class BaseController < ::ApplicationController
        ...
      end
    end
    
    # throws error, referencing constant that does not exist.
    # Should be < ::Admin::BaseController
    class OtherController < ::BaseController
    end
    

    和其他人一样,我的整个 rspec 套件会因错误 can't modify a frozen Array 而失败,在这种情况下,这本身并不是一个很有帮助的堆栈跟踪。

    希望这可以避免其他人花费数小时寻找其他东西!

    【讨论】:

    • 你是如何找到这个问题的原因的?
    【解决方案4】:

    当我遇到类似堆栈跟踪的相同错误时,它帮助我修复了工厂中的语法错误。

    【讨论】:

      【解决方案5】:

      首先检查您的测试数据库是否是最新的。

      rake db:test:prepare.

      【讨论】:

        【解决方案6】:

        如果这对将来的任何人有帮助,那就是数据库连接问题(在我的例子中是 Postgresql)。转到config/database.yml 文件并提供username:password: toor>

        将此添加到development: 组中。

        【讨论】:

          【解决方案7】:

          我会发布我的原因,但首先我会发布故障排除路径以帮助找到您的原因,因为此错误可能会在无数次出现原因。

          在大多数情况下这是一个相当无用的错误,并且堆栈跟踪是不可穿透的。我检查了堆栈中的所有 gem 代码,但没有一个指向问题的实际根源:

          # /Users/dh/.gem/gems/actionpack-5.2.3/lib/action_dispatch/middleware/stack.rb:76:in `insert'
          # /Users/dh/.gem/gems/actionpack-5.2.3/lib/action_dispatch/middleware/stack.rb:76:in `insert'
          # /Users/dh/.gem/gems/actionpack-5.2.3/lib/action_dispatch/middleware/stack.rb:83:in `insert_after'
          # /Users/dh/.gem/gems/request_store-1.4.1/lib/request_store/railtie.rb:5:in `block in <class:Railtie>'
          # /Users/dh/.gem/gems/railties-5.2.3/lib/rails/initializable.rb:32:in `instance_exec'
          # /Users/dh/.gem/gems/railties-5.2.3/lib/rails/initializable.rb:32:in `run'
          # /Users/dh/.gem/gems/railties-5.2.3/lib/rails/initializable.rb:61:in `block in run_initializers'
          # /Users/dh/.gem/gems/railties-5.2.3/lib/rails/initializable.rb:60:in `run_initializers'
          # /Users/dh/.gem/gems/railties-5.2.3/lib/rails/application.rb:361:in `initialize!'
          # ./config/environment.rb:5:in `<top (required)>'
          

          要找出您收到此错误的原因,请首先注释掉(或改回)您最后所做的任何事情,然后查看问题是否消失。如果没有,请恢复该行代码,然后git stash 隐藏所有您最近的更改并运行测试。

          这可能会解决问题,您可以git stash pop 并开始将您的更改分成两半,直到您确定问题所在。

          如果git stash 没有解决问题,那么您就知道问题出在您的代码外部,或者出现在您的上次提交中。

          如果您知道您之前的提交测试是干净的,请开始查看您的数据库、捆绑您的 gem、对您使用的 ENV 变量的更改或您的应用所依赖的其他环境因素。

          如果git stash 没有 解决了问题,并且您不知道您的上一次提交是否之前测试干净,请手动或使用git bisect 开始挖掘您的提交。如果您可以找到开始破坏测试的提交,您将能够追踪触发此错误的行。

          --

          至于我的特定问题,这是我添加的新 has_many 关系中的一个错字:

            has_many :marijunas, class_name: Drug
          

          一旦我缩小了对该行的更改,修复就变得很明显了:

            has_many :marijunas, class_name: :Drug
          

          【讨论】:

          • 你要做的有趣项目! :)
          【解决方案8】:

          我认为当我遇到类似问题时,是由于语法错误。尝试运行 rails db:migrate 以显示有关发生错误的行的更多信息

          【讨论】:

            【解决方案9】:

            就我而言,最近的 rails_admin 需要一些补充

            RuntimeError:未添加 RailsAdmin 所需的中间件
            要修复 tihs,请添加

            config.middleware.use ActionDispatch::Flash
            

            到 config/application.rb.

            然后所有的 rspecs 又变绿了。

            【讨论】:

              【解决方案10】:

              建议:在你的 development.rb 文件中添加config.eager_load = true 后尝试加载开发中的应用程序,这应该会给你一个实际有用的错误消息,指出问题代码。

              在我的例子中,一个 Rails 5.2 应用程序,它纯粹是从 Ruby 2.4.5 升级到 2.5.8 的结果,它指出唯一的问题是 unmatched range specifier in char-class 在一个已经工作多年的很长的正则表达式中。

              【讨论】:

                【解决方案11】:

                我尝试从 Rails 3 更新到 Rails 5。 我刚刚设置了config.eager_load 选项,它有所帮助。发送至falsetrue。请不要nil

                【讨论】:

                  【解决方案12】:

                  在我的情况下,这是由于我错过了解决的 git 冲突消息(类似 &gt;&gt;&gt;&gt; ... === ... &lt;&lt;&lt;&lt; 的消息),因此当 Rspec 尝试加载该类时出现语法错误。

                  --fail-fast 命令行选项在这种情况下没有帮助,因为错误发生在调用堆栈的更高位置,但您可以通过运行任何单个规范文件来查看实际错误。

                  【讨论】:

                    【解决方案13】:

                    我的两分钱,因为它可以帮助别人。我在将rails 4.2 升级到5.0 时遇到了同样的问题,我在某处看到一个帖子帖子,建议自己/一次运行一个规范测试。当我这样做时,我得到了一个不同的错误:superclass must be a Class 并指向我的新 .../models/application_record.rb 文件,其中我因遗漏而犯了语法错误:

                    class ApplicationRecord < ActiveRecord                              
                      self.abstract_class = true
                    end
                    

                    ActiveRecord 之后缺少::Base -- 第一行。

                    class ApplicationRecord < ActiveRecord::Base                                
                      self.abstract_class = true
                    end
                    

                    将其重新添加到修复了我的所有规格中。

                    【讨论】:

                      【解决方案14】:

                      尝试在您的环境文件中设置config.eager_load = true。这将在启动期间加载内存中的所有文件,如果有的话,将首先指出现有的语法错误。

                      【讨论】:

                        【解决方案15】:

                        那是因为我忘记在Gemfiletest组中添加bullet,查看我看到的错误顶部:

                        NameError:
                          uninitialized constant Bullet
                        

                        【讨论】:

                          【解决方案16】:

                          我在使用 Rails 6 处理应用程序时遇到了同样的问题。

                          问题是当我运行命令 rspec 时,我收到以下错误。下面的输出被缩短:

                          An error occurred while loading ./spec/routing/applyportal/school_histories_routing_spec.rb.
                          Failure/Error: require File.expand_path('../config/environment', __dir__)
                          
                          FrozenError:
                            can't modify frozen Array: ["/home/promisechukwuenyem/Projects/myapp/app/channels", 
                          

                          我是这样解决的

                          问题是我执行 git pull 后代码中的错误造成的。

                          由于我在开发中运行,我尝试使用以下方法删除我的数据库:

                          rails db:drop
                          

                          注意:这并没有删除我的数据库,因为该命令被我的代码中的错误中断。

                          然后我的终端中出现错误的实际位置是我的config/route.rb 文件。

                          我打开了我的config/route.rb 文件。然后我发现了这个:

                          # frozen_string_literal: true
                          
                          Rails.application.routes.draw do
                          <<<<<<< HEAD
                            resources :courses
                          =======
                            resources :results
                          >>>>>>> Added result and result upload feature
                            resources :books
                            resources :schools
                          end
                          

                          然后修改成这样:

                          # frozen_string_literal: true
                          
                          Rails.application.routes.draw do
                            resources :books
                            resources :results
                            resources :schools
                          end
                          

                          就是这样。

                          我希望这会有所帮助

                          【讨论】:

                            【解决方案17】:

                            当我删除 gem 'Faker' 但将 require 'faker' 留在 factory.rb 中时,我收到了这个错误

                            【讨论】:

                              【解决方案18】:

                              我通过rspec | less 找到了第一个错误

                              【讨论】:

                                【解决方案19】:

                                尝试在后台运行 redis 和 sidekiq。就我而言,这是原因之一。

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 2022-10-23
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2011-11-04
                                  • 2016-03-26
                                  • 2013-06-24
                                  • 1970-01-01
                                  • 2013-02-11
                                  相关资源
                                  最近更新 更多