【问题标题】:How do I suppress db creation when running a test on my model?在我的模型上运行测试时如何抑制数据库创建?
【发布时间】:2018-02-20 05:10:24
【问题描述】:

我正在尝试为我的模型编写一个简单的测试,我不需要创建数据库。我添加了以下文件以防止创建数据库

myenv:myproject nataliab$ cat lib/tasks/db/test.rake
Rake.application.remove_task 'db:test:prepare'

namespace :db do
  namespace :test do
    task :prepare do |t|
      # rewrite the task to not do anything you don't want
    end
  end
end

但是当我运行测试时,我仍然收到以下错误

myenv:myproject nataliab$ rails test -b test/models/my_model_test.rb
Running via Spring preloader in process 52504
/Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `async_exec': PG::InsufficientPrivilege: ERROR:  permission denied for relation schema_migrations (ActiveRecord::StatementInvalid)
: SELECT "schema_migrations".* FROM "schema_migrations"
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `block in exec_no_cache'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/abstract_adapter.rb:590:in `block in log'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/abstract_adapter.rb:583:in `log'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `exec_no_cache'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/postgresql_adapter.rb:585:in `execute_and_clear'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/postgresql/database_statements.rb:103:in `exec_query'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/abstract/database_statements.rb:377:in `select_prepared'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/abstract/database_statements.rb:39:in `select_all'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/connection_adapters/abstract/query_cache.rb:95:in `select_all'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/querying.rb:39:in `find_by_sql'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/relation.rb:702:in `exec_queries'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/relation.rb:583:in `load'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/relation.rb:260:in `records'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/relation/delegation.rb:38:in `map'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/migration.rb:1031:in `block in get_all_versions'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/deprecation/reporting.rb:36:in `silence'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/deprecation/instance_delegator.rb:20:in `silence'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/migration.rb:1029:in `get_all_versions'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/migration.rb:1043:in `needs_migration?'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/migration.rb:577:in `load_schema_if_pending!'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/migration.rb:592:in `block in maintain_test_schema!'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/migration.rb:823:in `suppress_messages'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/migration.rb:597:in `method_missing'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.5/lib/active_record/migration.rb:592:in `maintain_test_schema!'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/test_help.rb:14:in `<top (required)>'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `block in require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:259:in `load_dependency'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `require'
    from /Users/nataliab/Documents/workspace/myproject/test/test_helper.rb:3:in `<top (required)>'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `block in require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:259:in `load_dependency'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `require'
    from /Users/nataliab/Documents/workspace/myproject/test/models/my_model_test.rb:1:in `<top (required)>'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `block in require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:259:in `load_dependency'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/test_unit/runner.rb:48:in `block in load_tests'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/test_unit/runner.rb:48:in `each'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/test_unit/runner.rb:48:in `load_tests'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/test_unit/runner.rb:39:in `run'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/commands/test.rb:10:in `<top (required)>'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `block in require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:259:in `load_dependency'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/commands/commands_tasks.rb:138:in `require_command!'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/commands/commands_tasks.rb:95:in `test'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/commands/commands_tasks.rb:49:in `run_command!'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/railties-5.0.5/lib/rails/commands.rb:18:in `<top (required)>'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:293:in `block in require'
    from /Users/nataliab/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.5/lib/active_support/dependencies.rb:259:in `load_dependency'

我还需要做什么来防止发生任何数据库活动?

【问题讨论】:

  • 你为什么要这样做?只需使用 sqllite 设置一个测试数据库并完成它。为您的模型测试禁用数据库活动没有任何用处。
  • 因为我们确实需要在我们的测试环境中创建测试数据库,所以运行 PostGres。
  • 那我不确定是什么问题。如果您有一个可用于测试环境的数据库,为什么不使用它呢?这感觉像是一个 X/Y 问题。无论您遇到什么问题,为您的单元测试“关闭”模型背后的数据库几乎肯定不是正确的答案。
  • 这感觉就像你不知道我的问题的答案,只是给我跑来跑去。我们有开发、测试和生产环境。但我不希望在运行单元测试时创建测试数据库。
  • 没有人会“让你到处乱跑”,我试图通过找出你的实际问题来帮助你。您的要求没有意义,尤其是在没有上下文的情况下。

标签: ruby-on-rails database testing model ruby-on-rails-5


【解决方案1】:

ActiveRecord 与 DB 的耦合度如此之高,以至于无法做到。在解决读取迁移表的要求之后,您必须解决需要 DB 来创建模型属性(它为此读取数据库列)的事实,之后我不知道你面前的是什么,但我敢打赌你甚至不会接近完成猴子修补 AR(我可能错了)。

这就是rails的完成方式。

您可以做的可能是拥有从 AR(无表格模型)继承的模型,这些模型正在做您想做的任何事情,并且只在其他“经典”模型中使用它们?

我通常在遇到如此棘手的问题时将其视为您正在尝试“用头穿过墙壁”的暗示(墙壁是此处的框架,并非旨在处理此问题)并尝试想一个不同的设计(如上所述:“无桌子”模型)。

如果没有您项目的更多细节,很难提出更具体的建议。

【讨论】:

    【解决方案2】:

    如果您真的想在没有 DB 的情况下测试方法,请不要首先将其放入模型中。相反,您可以将它放在一个模块中(rails 用语中的一个问题):

    # app/models/concerns/foo.rb
    module Foo
      def bar
        'Hello world'
      end
    end
    

    然后,您只需在测试中创建一个由模块扩展的类:

    require "minitest/autorun"
    require "active_model/model"
    
    class TestFoo < Minitest::Test
      def setup
        @klass = Class.new do
          include ActiveModel::Model 
          include Foo
        end
      end
    
      def test_bar
        assert_equal 'Hello world', @klass.new.bar
      end
    end
    

    包含ActiveModel::Model 使测试替身的行为与任何其他模型一样,但没有持久层。

    否则,正如 meagar 和 meta 已经声明的那样,尝试在没有 DB 的情况下测试从 ActiveRecord::Base 继承的类是徒劳的。在没有数据库的情况下对模型进行单元测试的整个想法存在严重缺陷,因为 ActiveRecords 模型真正做的是与数据库交互。

    仅仅编写一个涵盖实际实现的测试将导致更好的敏锐度,这胜过在我的书中任何一天安抚一些原教旨主义单元测试的理想。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-02
      相关资源
      最近更新 更多