2012-07-05 13 views
7

¿Cómo puedo hacer algo como:rilspec de rieles: ¿cómo verificar la constante de un modelo?

it { should have_constant(:FIXED_LIST) } 

En mi modelo (registro activo) Tengo FIXED_LIST = 'A String'

No es un atributo db o un método y no he podido utilizar responds_to o has_attribute para probarlo (fallan). ¿Qué puedo usar para verificarlo? - Por cierto, tengo los Horda-Matchers instalados.

Respuesta

10

Sobre la base de la respuesta de David Chelimsky Tengo que esto funcione modificando ligeramente su código.

En una especificación de archivo/soporte/utilities.rb (o algún otro en la especificación/soporte) se puede poner:

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

Nota el uso de "RSpec :: Matchers.define" en lugar de " igualadores"

Esto permite poner a prueba para las constantes en sus especificaciones, como:

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

Nota el uso de 'have_constant' en lugar de 'have_const'

0

Usted podría utilizar

defined? YOUR_MODEL::FIXED_LIST 
+0

He intentado que '{debería definidos? (: EMPTY_TABLE)} El método' 'partidos no definidas, pero se habían '' para "expresión": String' –

+0

¿Qué pasa con 'should defined? (MODEL_NAME :: EMPTY_TABLE)'? – xdazz

+0

it {should defined? (ActivityDetail :: EMPTY_TABLE)} dio el método indefinido 'matches? ' para "constante": String –

6

Si usted quiere decir have_constant se puede definir una matcher personalizado para ello:

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

MyClass.should have_const(:CONST) 

Si usted está tratando de utilizar la sintaxis de una sola línea, se Tendrá que asegurarse de que el objeto es una clase (no es un ejemplo) o detectar en el matcher:

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

Consulte http://rubydoc.info/gems/rspec-expectations/RSpec/Matchers para obtener más información sobre los mezcladores personalizados.

HTH, David

+0

¿Dónde coloco el código de coincidencia? –

+0

Intenté ponerlo en spec/support/matchers pero obtengo 'método indefinido' matcher 'para main: Object (NoMethodError) 'en la línea 1 del código de coincidencia –

+0

He creado [a gist] (https: // gist .github.com/redconfetti/6356551) para esto con la solución que ideé. –

8

Se lee un poco tonto, pero:

describe MyClass do 

    it { should be_const_defined(:VERSION) } 

end 

La razón es que tiene Rspec comparadores "mágicas" para los métodos que comienzan con be_ y have_. Por ejemplo, it { should have_green_pants } afirmaría que el método has_green_pants? en el subject devuelve true.

De la misma manera, un ejemplo como it { should be_happy } afirmaría que el método happy? en el subject devuelve true. Por ejemplo, it { should be_const_defined(:VERSION) } afirma que const_defined?(:VERSION) devuelve true.

+0

Estoy usando RSpec 2.14.1 y no puedo hacer que esto funcione, no importa de qué manera lo intente. ¿Con qué versión (principal) de RSpec trabajaste? Siempre termino con el error 'NoMethodError ... undefined method' const_defined? ''. – Todd

+0

Lo siento demasiado tarde @RyanScottLewis, no puedo editar mi comentario anterior. Lo hice funcionar de la siguiente manera: 'it {subject.class.should be_const_defined (: MY_CONST)}'. El problema probablemente se debió a que se verificaba en contra del "sujeto" en lugar de la Clase. – Todd

+0

Si 'describes' tu clase (sin comillas), esto debería funcionar como se indica en rspec 3.4. – randallreedjr

2

Advertencia para cualquiera que intente probar que las constantes están definidas: Si su código hace referencia a una constante indefinida mientras define una clase, sus especificaciones se bloquearán antes de que lleguen a su prueba.

Esto puede llevar a creer que

expect { FOO }.to_not raise_error 

está fallando para coger el NameError, porque obtendrá un gran seguimiento de la pila, en lugar de un buen "espera no aumentar de error, pero se crió NameError. "

En medio del enorme rastro de la pila, puede ser difícil notar que su prueba se está rompiendo en la línea 1: requre "spec/spec_helper" porque su aplicación completa no carga antes de llegar a su prueba real.

Esto puede suceder si tiene constantes definidas dinámicamente, como lo hace ActiveHash :: Enum, y luego las usa en la definición de otra constante. No se moleste en probar que existen, cada especificación de su aplicación fallará si una de ellas no se define.

0

En RSpec 2, yo era capaz de conseguir que esto funcione en una línea de la siguiente manera:

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

Es decir, comprobar contra la clase, en lugar de la instancia.

0

en mi modelo

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

En Mis 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 
Cuestiones relacionadas