Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a custom validator?

I have the following validator:

# Source: http://guides.rubyonrails.org/active_record_validations_callbacks.html#custom-validators # app/validators/email_validator.rb  class EmailValidator < ActiveModel::EachValidator   def validate_each(object, attribute, value)     unless value =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i       object.errors[attribute] << (options[:message] || "is not formatted properly")      end   end end 

I would like to be able to test this in RSpec inside of my lib directory. The problem so far is I am not sure how to initialize an EachValidator.

like image 965
GTDev Avatar asked Oct 12 '11 17:10

GTDev


People also ask

What methods should you implement for your custom validator?

Implementing the Validator Interface A Validator implementation must contain a constructor, a set of accessor methods for any attributes on the tag, and a validate method, which overrides the validate method of the Validator interface.

How do I create a custom validator?

Custom validators take the value from the FormControl , where every input acts as a FormControl . So let's create a form along with a validator function. Create a new file called customvalidator. validator.

What does custom validator do?

Use the CustomValidator control to provide a user-defined validation function for an input control. The CustomValidator control is a separate control from the input control it validates, which allows you to control where the validation message is displayed. Validation controls always perform validation on the server.


1 Answers

I am not a huge fan of the other approach because it ties the test too close to the implementation. Also, it's fairly hard to follow. This is the approach I ultimately use. Please keep in mind that this is a gross oversimplification of what my validator actually did... just wanted to demonstrate it more simply. There are definitely optimizations to be made

class OmniauthValidator < ActiveModel::Validator   def validate(record)     if !record.omniauth_provider.nil? && !%w(facebook github).include?(record.omniauth_provider)       record.errors[:omniauth_provider] << 'Invalid omniauth provider'     end   end end 

Associated Spec:

require 'spec_helper'  class Validatable   include ActiveModel::Validations   validates_with OmniauthValidator   attr_accessor  :omniauth_provider end  describe OmniauthValidator do   subject { Validatable.new }    context 'without provider' do     it 'is valid' do       expect(subject).to be_valid     end   end    context 'with valid provider' do     it 'is valid' do       subject.stubs(omniauth_provider: 'facebook')        expect(subject).to be_valid     end   end    context 'with unused provider' do     it 'is invalid' do       subject.stubs(omniauth_provider: 'twitter')        expect(subject).not_to be_valid       expect(subject).to have(1).error_on(:omniauth_provider)     end   end end 

Basically my approach is to create a fake object "Validatable" so that we can actually test the results on it rather than have expectations for each part of the implementation

like image 185
Neal Avatar answered Oct 03 '22 23:10

Neal