Rails rspec - how to check persistent model?

How can I do something like:

it { should have_constant(:FIXED_LIST) } 

In my model (active record), I have FIXED_LIST = 'A String'

This is not a db attribute or method, and I could not use responds_to or has_attribute to check for it (they fail). What can I use for verification. - btw I have the appropriate sockets installed.

+7
source share
7 answers

Based on David Chelimsky's answer, I have this to change his code a bit.

In the file spec / support / utilities.rb (or some other in spec / support) you can put:

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

Note the use of "RSpec :: Matchers.define" instead of "matches"

This allows you to test constants in your specifications, for example:

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

Note the use of "has_constant" instead of "has_const"

+10
source

He reads a little silly, but:

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

The reason is that Rspec has โ€œmagicโ€ matches for methods starting with be_ and have_ . For example, it { should have_green_pants } will claim that the has_green_pants? method has_green_pants? on subject returns true .

In the same way, an example, for example it { should be_happy } , would claim that the happy? on subject returns true .

So, the example it { should be_const_defined(:VERSION) } states that const_defined?(:VERSION) returns true .

+8
source

If you want to say have_constant , you can define a custom layout for it:

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

If you are trying to use single-layer syntax, you need to make sure that the object is a class (not an instance) or check it in matches:

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

For more information on user mappings, see http://rubydoc.info/gems/rspec-expectations/RSpec/Matchers .

NTN, David

+6
source

Warning to anyone trying to verify that constants are defined: If your code refers to an undefined constant when defining a class, then your specifications will break before they get into your test.

It can make you believe that

 expect { FOO }.to_not raise_error 

it is not possible to catch NameError because you will get a large stack trace, and not a good "expected so as not to raise an error, but raise the NameError value".

Amid the huge stack trace, it can be hard to notice that your test is actually crashing on line 1: requre "spec / spec_helper" because your whole application does not load before it reaches your actual test.

This can happen if you have dynamically defined constants, for example, using ActiveHash :: Enum, and then use them in the definition of another constant. Do not bother checking that they exist, each specification in your application will fail if one of them is not defined.

+2
source

you can use

 defined? YOUR_MODEL::FIXED_LIST 
0
source

In RSpec 2, I managed to get this to work on a single line as follows:

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

That is, check the class, not the instance.

0
source

In my model

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

In My 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 
0
source

All Articles