rails rspec - Comment vérifier une constante de modèle?

Comment puis-je faire quelque chose comme:

it { should have_constant(:FIXED_LIST) }

Dans mon modèle (enregistrement actif) j'ai FIXED_LIST = 'A String'

ce n'est pas un attribut db ou une méthode et je n'ai pas été capable d'utiliser responds_to ou has_attribute pour le tester (ils échouent). Que puis-je utiliser le vérifier. - btw j'ai le shoulda-rapprochement installé.

8
demandé sur Michael Durrant 2012-07-05 07:52:18

7 réponses

Dans un fichier spec/support/services publics.rb (ou d'une autre dans spec/support) vous pouvez mettre:

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

noter l'utilisation de " RSpec:: Matchers.définir" au lieu de "rapprochement"

ceci permet de tester les constantes dans vos spécifications, comme:

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

Remarque: l'utilisation de "have_constant" au lieu de "have_const"

11
répondu dutchstrider 2012-12-17 15:22:49

Il lit un peu ridicule, mais:

describe MyClass do

  it { should be_const_defined(:VERSION) }

end

la raison en est que Rspec a des marqueurs "magiques" pour les méthodes commençant par be_ et have_. Par exemple, it { should have_green_pants } affirmerait que les has_green_pants? méthode subject retourne true.

De la même manière, un exemple comme it { should be_happy } affirmerait que les happy? méthode subject retourne true.

alors, l'exemple it { should be_const_defined(:VERSION) } affirme que const_defined?(:VERSION) retourne true.

8
répondu RyanScottLewis 2013-04-16 23:41:09

Si vous voulez dire have_constant vous pouvez définir une correspondance personnalisée pour:

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

MyClass.should have_const(:CONST)

si vous essayez d'utiliser la syntaxe mono-liner, vous devez vous assurer que le sujet est une classe (pas une instance) ou vérifier dans le matcher:

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

voir http://rubydoc.info/gems/rspec-expectations/RSpec/Matchers pour plus d'information sur les tapis sur mesure.

HTH, David

6
répondu David Chelimsky 2012-07-05 04:35:15

Un avertissement à quiconque essaie de tester que les constantes sont définies: Si votre code références une constante non définie lors de la définition d'une classe, alors vos spécifications s'écraseront avant qu'elles n'arrivent à votre test.

cela peut vous conduire à croire que

expect { FOO }.to_not raise_error

ne parvient pas à attraper le NameError, parce que vous obtiendrez une grande trace de pile, au lieu d'un joli "prévu de ne pas soulever d'erreur, mais un NameError surélevé."

Au milieu de la trace énorme de pile, il peut être difficile de remarquer que votre test est en train de s'écraser sur la ligne 1: requre "spec/spec_helper" parce que toute votre application ne se charge pas avant qu'elle n'arrive à votre test réel.

cela peut se produire si vous avez des constantes définies dynamiquement, comme C'est le cas avec ActiveHash::Enum, et que vous les utilisez ensuite dans la définition d'une autre constante. Ne prenez pas la peine de tester qu'ils existent, toutes les spécifications de votre application vont se planter si l'un d'eux échoue à être défini.

2
répondu Avram 2014-04-04 13:41:21

Vous pouvez utiliser

defined? YOUR_MODEL::FIXED_LIST
0
répondu xdazz 2012-07-05 03:57:16

Dans RSpec 2, j'ai pu obtenir que cela fonctionne dans une ligne comme suit:

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

c'est-à-dire, cochez la classe au lieu de l'instance.

0
répondu Todd 2016-03-24 21:37:15

Dans Mon modèle

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

Dans Mon 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
répondu Juarez Lustosa 2017-03-03 17:10:19