2012-07-05 23 views
7

我怎麼可以這樣做:rails rspec - 如何檢查模型常量?

it { should have_constant(:FIXED_LIST) } 

在我的模型(活動記錄)我有FIXED_LIST = 'A String'

這不是一個數據庫屬性或方法,我一直無法使用responds_tohas_attribute測試它(他們失敗)。我可以用什麼來檢查它。 - 順便說一句,我已安裝了應用程序匹配器。

回答

10

基於大衛赫利姆斯基的答案我有這個通過稍微修改了代碼工作。

在文件規範/支持/ utilities.rb(或一些其他的規格/支),你可以把:

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

注意使用「的RSpec :: Matchers.define」中的「代替匹配器」

這使得以測試你的規格常量,如:

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

注意使用‘have_constant’以代替‘have_const’

0

你可以使用

defined? YOUR_MODEL::FIXED_LIST 
+0

我試着'它{應當界定?(:EMPTY_TABLE)}'但得到'未定義的方法'比賽」 for「expression」:String' –

+0

'應該定義什麼?(MODEL_NAME :: EMPTY_TABLE)'? – xdazz

+0

它{應該定義?(ActivityDetail :: EMPTY_TABLE)}給了未定義的方法'匹配?'爲「常量」:字符串 –

6

如果你想說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, 大衛

+0

我在哪裏放置匹配代碼? –

+0

我試着把它放在spec/support/matchers中,但是我在匹配代碼的第一行得到了'main:Object(NoMethodError)'的'未定義方法'matcher' –

+0

我做了[一個要點](https:// gist .github.com/redconfetti/6356551)用我設計的解決方案。 –

8

它讀取有點傻,但是:

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

+0

我正在使用RSpec 2.14.1,無論我嘗試哪種方式,都無法使其工作。哪個(主要)版本的RSpec你是否得到這個工作?我總是以'NoMethodError ...未定義的方法'const_defined?'錯誤結束。 – Todd

+0

抱歉太晚了@RyanScottLewis,不能編輯我上面的評論。我得到它的工作如下:'it {subject.class.should be_const_defined(:MY_CONST)}'。這個問題大概是因爲它檢查了「subject」而不是Class。 – Todd

+0

如果你正在描述你的課程(沒有引號),這應該按照rspec 3.4的規定工作。 – randallreedjr

2

對試圖測試常量的任何人發出警告:如果您的代碼在定義類時引用了未定義的常量,那麼您的規格將在他們進行測試之前崩潰。

這可能會導致您認爲

expect { FOO }.to_not raise_error 

未能趕上NameError,因爲你會得到一個很大的堆棧跟蹤,而不是一個很好的「預計不會引發錯誤,但上調NameError。 「

在巨大的堆棧跟蹤中,可能很難注意到您的測試實際上在第1行崩潰:請求「spec/spec_helper」,因爲您的整個應用程序在到達實際測試之前未能加載。

如果您有動態定義的常量(例如ActiveHash :: Enum完成),然後在另一個常量的定義中使用它們,則會發生這種情況。不要打擾他們存在的測試,如果你的應用程序中的一個未能定義,你的應用程序中的每個規格都會崩潰。

0

在RSpec的2,我能得到這個在一行中的工作方式如下:

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

,即檢查而不是實例對類。

0

在我的模型

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 
相關問題