2011-09-14 21 views
29

Tengo la siguiente validación en mi ActiveRecord.Cómo puedo probar: validación de inclusión en Rails usando RSpec

validates :active, :inclusion => {:in => ['Y', 'N']} 

Estoy utilizando lo siguiente para probar las validaciones de mi modelo.

should_not allow_value('A').for(:active) 
should allow_value('Y').for(:active) 
should allow_value('N').for(:active) 

¿Hay un limpiador y más a través de la forma de probar esto? Actualmente estoy usando RSpec2 y debería corresponder.

EDITAR

Después de algún mirando a su alrededor sólo he encontrado, esto probablemente una forma 'bien' de pruebas de esta, la debería no proporciona nada de esto y cualquier persona que lo requiera puede escribir su propio matcher personalizado para ello . (Y probablemente contribuir de nuevo al proyecto). Algunos enlaces a discusiones que podrían ser interesantes:

  • Enlaces que indican lo anterior. Link 1, Link 2

  • should_ensure_value_in_range Este viene cerca de lo que se puede utilizar, pero sólo acepta rangos y no una lista de valores. El emparejador personalizado se puede basar en esto.

Respuesta

53

Use shoulda_matchers

En versiones recientes de shoulda-matchers (por lo menos a partir de la versión 2.7.0), que puede hacer:

expect(subject).to validate_inclusion_of(:active).in_array(%w[Y N]) 

Se utiliza para comprobar que la matriz de valores aceptables en la validación coincide exactamente con esta especificación.

En versiones anteriores,> = V1.4, shoulda_matchers soporta esta sintaxis:

it {should ensure_inclusion_of(:active).in_array(%w[Y N]) } 
+0

Para comprobar que no permite otros valores, puede hacer algo como: 'it {should_not allow_value ('?'). For (: active)}' - como dijo, no puede verificar todos los valores posibles, pero haciendo esto además de verificar todos los valores permitidos parece una cobertura razonable. – bjnord

+0

El shoulda_matcher al que se refirió ** funciona ** como lo indicó originalmente, es decir, no permite valores que no estén en la matriz proporcionada. [Ver documentación] (https://github.com/thoughtbot/shoulda-matchers#ensure_inclusion_of). Para una buena medida, probé esto en una aplicación de Rails y funciona correctamente. –

+1

@LarsLevie - Gracias por el comentario. Parece que cambiaron la validación para comprobar 'disallows_value_outside_of_array?'. Mira el viejo https://github.com/thoughtbot/shoulda-matchers/blob/v1.2.0/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb#L86 vs ahora https://github.com/thoughtbot/shoulda- matchers/blob/15abdf066732828034efea751c2937aa81d080fe/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb # L90 –

1

encontré uno matcher la debería encargo (en uno de los proyectos que estaba trabajando), que trata de acercarse a probar algo como esto:

Ejemplos:

it { should validate_inclusion_check_constraint_on :status, :allowed_values => %w(Open Resolved Closed) } 
it { should validate_inclusion_check_constraint_on :age, :allowed_values => 0..100 } 

El matcher intenta asegurarse de que hay una restricción DB que explota cuando intenta guardarla. Intentaré dar la esencia de la idea. ¿Los partidos? aplicación hace algo como:

begin 
    @allowed_values.each do |value| 
     @subject.send("#{@attribute}=", value) 
     @subject.save(:validate => false) 
    end 
    rescue ::ActiveRecord::StatementInvalid => e 
    # Returns false if the exception message contains a string matching the error throw by SQL db 
    end 

supongo que si nos cambiamos ligeramente por encima de la de decir @subject.save y dejar que la validación de los carriles estallar, podemos devolver false cuando la cadena de excepción contiene algo que se cierran coincide con el mensaje de error verdadera excepción.

Sé que esto está lejos de ser perfecto para contribuir al proyecto, pero supongo que no sería una mala idea agregarlo a tu proyecto como un evaluador personalizado si realmente quieres probar la validación de :inclusion.

+0

voy a aceptar mi propia respuesta aquí, ya que parece que no puede encontrar nada más, pero no dude en criticar cómo la solución anterior puede fallar, o incluso es una mala idea molestarse en hacer esto. – jake

23

Si tiene más elementos para probar que un S/N booleano, entonces también puede probar.

it "should allow valid values" do 
    %w(item1 item2 item3 item4).each do |v| 
    should allow_value(v).for(:field) 
    end 
end 
it { should_not allow_value("other").for(:role) } 

También puede reemplazar el %w() con una constante que ha definido en el modelo de modo que prueba que sólo los valores constantes están permitidos.

CONSTANT = %w[item1 item2 item3 item4] 
validates :field, :inclusion => CONSTANT 

Entonces la prueba:

it "should allow valid values" do 
    Model::CONSTANT.each do |v| 
    should allow_value(v).for(:field) 
    end 
end 
Cuestiones relacionadas