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é.
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"
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
.
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
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.
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.
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