Last active
December 14, 2015 12:18
-
-
Save kianw/5085085 to your computer and use it in GitHub Desktop.
Thorough Testing of Association Validations --- RSpec examples that will test that a child object is correctly validating its association with a parent object. ActiveRecord will assign a project_id to the task if you assign a saved Project to project. If you assign an unsaved/new Project to project, it will leave project_id blank. Thus, we want …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Examples | |
context "validations" do | |
let(:child) { FactoryGirl.build(:child) } # Fill in enough to ensure that the Child is valid except for the association | |
it "should not fail if an associated valid Parent is present" do | |
child.parent = FactoryGirl.build(:parent) | |
child.valid?.should be_true | |
child.errors.should be_empty | |
end | |
it "should not fail if a parent-id is present and represents a valid Party" do | |
parent = FactoryGirl.create(:parent) | |
child.parent_id = parent.id | |
child.valid?.should be_true | |
child.errors.should be_empty | |
end | |
it "should fail if there is not an associated parent or parent-id" do | |
child.valid?.should be_false | |
child.errors.should_not be_empty | |
end | |
it "should fail if there is a parent-id which does not represent a valid Parent" do | |
child.parent_id = -1 | |
child.valid?.should be_false | |
child.errors.should_not be_empty | |
end | |
it "should fail if there is a parent-id which represents a saved but invalid Parent" do | |
parent = FactoryGirl.create(:parent) | |
child.parent_id = parent.id | |
child.parent.stub(:valid?).and_return(false) | |
child.parent.stub(:errors).and_return({:base => 'testing'}) | |
child.valid?.should be_false | |
child.errors.should_not be_empty | |
end | |
it "should fail if there is an associated existing Parent which is not valid" do | |
child.parent = FactoryGirl.create(:parent) | |
child.parent.stub(:valid?).and_return(false) | |
child.parent.stub(:errors).and_return({:base => 'testing'}) | |
child.valid?.should be_false | |
child.errors.should_not be_empty | |
end | |
it "should fail if there is an associated new Parent which is not valid" do | |
child.parent = FactoryGirl.build(:parent) | |
child.parent.stub(:valid?).and_return(false) | |
child.parent.stub(:errors).and_return({:base => 'testing'}) | |
child.valid?.should be_false | |
child.errors.should_not be_empty | |
end | |
end | |
# The validations in the model that will make these examples pass: | |
validates_associated :parent | |
validates_presence_of :parent_id, :unless => Proc.new {|o| o.parent.try(:new_record?)} | |
validates_presence_of :parent, :if => Proc.new {|o| o.parent_id} | |
# A more abstract version of the examples, suitable to be used as a mixin | |
# Validates an association. Ensure that +object+ is available, either by defining it through | |
# a helper, or using +let+. | |
# - +association_name+ should be a symbol representing the name of the association. +object+ should | |
# respond to this | |
# - +factory_name+ should be a symbol that is the name of a FactoryGirl factory for the associated object | |
module ValidatesAssociatedSpec | |
shared_examples_for "any validated association" do |association_name, factory_name=association_name| | |
context "validate #{association_name}" do | |
it "should not fail if an associated valid #{association_name} is present" do | |
object.send(:"#{association_name}=", FactoryGirl.build(factory_name)) | |
object.valid?.should be_true | |
object.errors.should be_empty | |
end | |
it "should not fail if a #{association_name}-id is present and represents a valid #{association_name}" do | |
assoc = FactoryGirl.create(factory_name) | |
object.send(:"#{association_name}_id=", assoc.id) | |
object.valid?.should be_true | |
object.errors.should be_empty | |
end | |
it "should fail if there is not an associated #{association_name} or #{association_name}-id" do | |
object.valid?.should be_false | |
object.errors.should_not be_empty | |
object.errors[:"#{association_name}_id"].should eq(["can't be blank"]) | |
end | |
it "should fail if there is a #{association_name}-id which does not represent a saved #{association_name}" do | |
object.send(:"#{association_name}_id=", -1) | |
object.valid?.should be_false | |
object.errors.should_not be_empty | |
object.errors[association_name].should eq(["can't be blank"]) | |
end | |
it "should fail if there is a #{association_name}-id which represents a saved but invalid #{association_name}" do | |
assoc = FactoryGirl.create(factory_name) | |
object.party_id = assoc.id | |
object.send(association_name.to_sym).stub(:valid?).and_return(false) | |
object.send(association_name.to_sym).stub(:errors).and_return({:base => 'testing'}) | |
object.valid?.should be_false | |
object.errors.should_not be_empty | |
object.errors[association_name].should eq(["is invalid"]) | |
end | |
it "should fail if there is an associated existing #{association_name} which is not valid" do | |
object.send(:"#{association_name}=", FactoryGirl.create(factory_name)) | |
object.send(association_name.to_sym).stub(:valid?).and_return(false) | |
object.send(association_name.to_sym).stub(:errors).and_return({:base => 'testing'}) | |
object.valid?.should be_false | |
object.errors.should_not be_empty | |
object.errors[association_name].should eq(["is invalid"]) | |
end | |
it "should fail if there is an associated new #{association_name} which is not valid" do | |
object.send(:"#{association_name}=", FactoryGirl.build(factory_name)) | |
object.send(association_name.to_sym).stub(:valid?).and_return(false) | |
object.send(association_name.to_sym).stub(:errors).and_return({:base => 'testing'}) | |
object.valid?.should be_false | |
object.errors.should_not be_empty | |
object.errors[association_name].should eq(["is invalid"]) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment