Skip to content

Instantly share code, notes, and snippets.

@kianw
Last active December 14, 2015 12:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kianw/5085085 to your computer and use it in GitHub Desktop.
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 …
# 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