【问题标题】:rails rspec - how to check for a model constant?rails rspec - 如何检查模型常数?
【发布时间】:2012-07-05 03:52:18
【问题描述】:

我该怎么做:

it { should have_constant(:FIXED_LIST) }

在我的模型中(活动记录)我有FIXED_LIST = 'A String'

它不是 db 属性或方法,我无法使用 responds_tohas_attribute 对其进行测试(它们失败了)。我可以用什么来检查它。 - 顺便说一句,我已经安装了 shoulda-matchers。

【问题讨论】:

    标签: ruby rspec constants


    【解决方案1】:

    根据 David Chelimsky 的回答,我可以通过稍微修改他的代码来实现这一点。

    您可以在文件 spec/support/utilities.rb(或 spec/support 中的其他文件)中放置:

    RSpec::Matchers.define :have_constant do |const|
      match do |owner|
        owner.const_defined?(const)
      end
    end
    

    注意使用“RSpec::Matchers.define”而不是“matchers”

    这允许测试规范中的常量,例如:

     it "should have a fixed list constant" do
        YourModel.should have_constant(:FIXED_LIST)
     end
    

    注意使用“have_constant”而不是“have_const”

    【讨论】:

    【解决方案2】:

    读起来有点傻,但是:

    describe MyClass do
    
      it { should be_const_defined(:VERSION) }
    
    end
    

    原因是 Rspec 为以be_have_ 开头的方法提供了“神奇”匹配器。例如,it { should have_green_pants } 会断言subject 上的has_green_pants? 方法返回true

    以同样的方式,it { should be_happy } 等示例将断言 subject 上的 happy? 方法返回 true

    因此,示例it { should be_const_defined(:VERSION) } 断言const_defined?(:VERSION) 返回true

    【讨论】:

    • 我正在使用 RSpec 2.14.1,无论我尝试哪种方式,我都无法让它工作。您使用的是哪个(主要)版本的 RSpec?我总是以 NoMethodError ... undefined method const_defined?'` 错误告终。
    • 抱歉太晚了@RyanScottLewis,无法编辑我上面的评论。我让它按如下方式工作:it { subject.class.should be_const_defined(:MY_CONST) }。问题可能是由于它检查 subject 而不是 Class。
    • 如果你是describe你的班级(不带引号),这应该按照 rspec 3.4 的规定工作。
    • 这绝对应该是公认的答案。简洁,简洁的单行语法,无需定义额外的匹配器
    【解决方案3】:

    如果你想说have_constant,你可以为它定义一个自定义匹配器:

    matcher :have_constant do |const|
      match do |owner|
        owner.const_defined?(const)
      end
    end
    
    MyClass.should have_const(:CONST)
    

    如果您尝试使用单行语法,则需要确保主题是一个类(不是实例)或在匹配器中检查它:

    matcher :have_constant do |const|
      match do |owner|
        (owner.is_a?(Class) ? owner : owner.class).const_defined?(const)
      end
    end
    

    有关自定义匹配器的更多信息,请参阅http://rubydoc.info/gems/rspec-expectations/RSpec/Matchers

    HTH, 大卫

    【讨论】:

    • 我尝试将它放在 spec/support/matchers 中,但我在匹配器代码的第 1 行得到 undefined method matcher' for main:Object (NoMethodError)`
    • 我用我设计的解决方案为此创建了a gist
    【解决方案4】:

    另一个简单地确保定义常量的选项——不用担心它是用什么定义的:

    it 'has a WHATEVER constant' do
      expect(SomeClass::WHATEVER).not_to be_nil
    end
    

    【讨论】:

      【解决方案5】:

      对尝试测试已定义常量的任何人的警告:如果您的代码在定义类时引用未定义的常量,那么您的规范将在测试之前崩溃。

      这会让你相信

      expect { FOO }.to_not raise_error
      

      未能捕捉到 NameError,因为你会得到一个很大的堆栈跟踪,而不是一个很好的“预计不会引发错误,但引发了 NameError”。

      在巨大的堆栈跟踪中,很难注意到您的测试实际上在第 1 行崩溃:请求“spec/spec_helper”,因为您的整个应用程序在进入实际测试之前无法加载。

      如果您有动态定义的常量,例如由 ActiveHash::Enum 完成,然后您在另一个常量的定义中使用它们,就会发生这种情况。不要费心测试它们是否存在,如果其中一个未定义,您应用中的每个规范都会崩溃。

      【讨论】:

        【解决方案6】:

        你可以使用

        defined? YOUR_MODEL::FIXED_LIST
        

        【讨论】:

        • 我尝试了it { should defined?(:EMPTY_TABLE) },但得到了undefined method matches?对于“表达式”:字符串`
        • should defined?(MODEL_NAME::EMPTY_TABLE) 呢?
        • it { should defined?(ActivityDetail::EMPTY_TABLE) } 给出了未定义的方法“匹配?”对于“常量”:字符串
        【解决方案7】:

        在 RSpec 2 中,我能够让它在一行中工作,如下所示:

        it { subject.class.should be_const_defined(:MY_CONST) }

        也就是说,检查类,而不是实例。

        【讨论】:

          【解决方案8】:

          在我的模型中

           class Role < ActiveRecord::Base
             ROLE_ADMIN = "Administrador"     
           end
          

          在我的 rspec 中

           RSpec.describe Role, type: :model do
            let(:fake_class) { Class.new }
          
            describe "set constants" do
              before { stub_const("#{described_class}", fake_class) }
          
              it { expect(described_class::ROLE_ADMIN).to eq("Administrador") }
            end
          end
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-11-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多