The most straight-forward way is to create a model and use the
valid? method to determine if it is valid or not. For an example I'm going to reuse the PhoneNumber class I defined in a previous entry on ActiveRecord Unit Testing. The following code shows the three tests I've written to ensure that I've correctly defined a validates_presence_of for digits.class PhoneNumberTest < Test::Unit::TestCaseAfter adding the validates_presence_of call to the PhoneNumber class, all the above tests pass.
Column = ActiveRecord::ConnectionAdapters::Column
test "digits are required to be valid" do
PhoneNumber.stubs(:columns).returns([Column.new("digits", nil, "string", false)])
number = PhoneNumber.new(:digits => "1234567890")
assert_equal true, number.valid?
end
test "invalid with no digits " do
PhoneNumber.stubs(:columns).returns([Column.new("digits", nil, "string", false)])
number = PhoneNumber.new()
assert_equal false, number.valid?
end
test "errors include digits on invalid digits" do
PhoneNumber.stubs(:columns).returns([Column.new("digits", nil, "string", false)])
number = PhoneNumber.new()
number.valid?
assert_equal "can't be blank", number.errors.on('digits')
end
end
class PhoneNumber < ActiveRecord::BaseThis all works fine, but I'm not sure it's necessary to actually cause a validation to occur just to test that one has been defined.
validates_presence_of :digits
end
An alternative test implementation could mock the
validates_presence_of call and load the file. If the validates_presence_of is defined correctly the class methods will be invoked.class PhoneNumberTest < Test::Unit::TestCaseThis method of testing doesn't require actually creating a PhoneNumber instance, instead it tests that the PhoneNumber validations are defined correctly.
Column = ActiveRecord::ConnectionAdapters::Column
test "validates_presence_of is defined for digits" do
PhoneNumber.expects(:validates_presence_of).with(:digits)
load "#{RAILS_ROOT}/app/models/phone_number.rb"
end
end
The load call is a bit messy; however, we can clean that up by adding another method to ActiveRecord::Base.
class << ActiveRecord::BaseFollowing the above code change the test can be rewritten to the code shown below.
def standard_path
File.expand_path("#{RAILS_ROOT}/app/models/#{self.name.underscore}.rb")
end
end
class PhoneNumberTest < Test::Unit::TestCaseWhich implementation is better? Both implementations provide pros and cons. I suggest trying both out to determine which works best for you (or your team).
Column = ActiveRecord::ConnectionAdapters::Column
test "validates_presence_of is defined for digits" do
PhoneNumber.expects(:validates_presence_of).with(:digits)
load PhoneNumber.standard_path
end
end