I am writing tests for a RoR Gem that has a validation that is dependent on a configuration variable:
class MyModel < ApplicationRecord
validates_length_of :field_name, minimum: GemName.minimum_field_length
end
I can verify that this configuration option works as expected, however I want to ensure that it is covered in test:
class MyModelTest < ActiveSupport::TestCase
test "field length is validated" do
model = MyModel(field_name: 'a' * 25
# Default minimum length is 20
assert model.valid?
# Test different length validation
GemName.minimum_field_length = 30
assert_not model.valid?
end
end
The second assertion fails (the model is valid). If I add a debugger there and inspect, GemName.minimum_field_length
gives me 30
, indicating that it is changed, but if I look at the result of MyModel.validators
, the minimum is still the original default value of 20. Presumably this is because the validators are created once, either when the test starts or when the model is called the first time (I have tried creating a new instance of MyModel
after changing the config with no luck). Is there a way similar to .reset_column_information
to refresh the model validators with the new configuration value during the test?
The problem is that defining a minimum
length in a validation like this
validates_length_of :field_name, minimum: GemName.minimum_field_length
then it sets the minimum only once when the file is read for the first time. When GemName.minimum_field_length
changes, then the configuration of the validator is not changed anymore.
But when you initialize the validator with a lambda instead, then the lambda would be evaluated on every validator call and should therefore pick up changes.
Try this instead:
validates_length_of :field_name, minimum: -> { GemName.minimum_field_length }
When you only want to ensure that the minimum length of the field equals the gem's configured minimum length, then you might want to write a test that checks if both values are equal, like this:
minimum_field_name_length = MyModel.validators_on(:field_name)
.select { |v| v.is_a?(LengthValidator) }
.first
.options[:minimum]
assert_equal minimum_field_name_length, GemName.minimum_field_length