Reputation: 2504
I'm trying to test an association.
I have these two classes:
class Survey < ActiveRecord::Base
has_many :users, through: :users_surveys
has_many :users_surveys
def update_or_create_result(user_id, result, target)
user_survey = users_surveys.find_or_create_by(user_id: params[:user_id])
if survey_passed?(result, target)
user_survey.completed!
end
end
end
class User < ActiveRecord::Base
has_many :surveys, through: :users_surveys
has_many :users_surveys
end
class UsersSurvey < ActiveRecord::Base
belongs_to :user
belongs_to :survey
end
How can I test with RSpec if the association between survey and user is created?
Upvotes: 6
Views: 7738
Reputation: 102398
The shoulda-matchers
gem provides some nifty matchers that test the association is declared and that the correct database fields and foreign keys exist:
describe User do
it { should have_many(:surveys) }
end
If you for some reason have gem-o-phobia and just want to test it straight off the bat you can use ActiveRecord::Reflection
to get information about the relations of a model:
describe User do
it "should have_many :surveys" do
expect(User.reflect_on_association(:surveys).macro).to eq :has_many
end
end
describe Survey do
it "should belong_to user" do
expect(Survey.reflect_on_association(:user).macro).to eq :belongs_to
expect(Survey.column_names).to include :user_id
end
end
You can also test the behavior of your models by creating an associated object - however if you have validation requirements than your specs sometimes end up somewhat muddled since your spec for A needs to fullfil the requirements for B.
Upvotes: 3
Reputation: 51191
Assuming you have user
and survey
variables, it's as simple as this:
user.surveys.should include(survey)
Since your question is a bit unclear, my answer checks if association between actual two records is created.
Upvotes: 2
Reputation: 52377
Just want to emphasize, that current nex syntax for RSpec is the following:
describe User do
it { is_expected.to have_many(:surveys) } # shortcut for expect(subject).to
end
describe Survey do
it { is_expected.to belong_to(:user) }
end
should
is considered to be old syntax for quite a few years now :)
Upvotes: 5
Reputation: 20033
If you are using or want to use Shoulda, this is straightforward
describe User do
it { should have_many(:surveys) }
end
describe Survey do
it { should belong_to(:user) }
end
Or, if you're testing a has_many :through
, like it seems to be your case, use
describe User do
it { should have_many(:surveys).through(:user_survey) }
end
If you do not want to use Shoulda, you need to get a little creative
describe User do
let(:user) { User.new }
it "should define the association" do
expect(user).to have(:no).errors_on(:surveys)
end
end
describe Survey do
let(:user) { User.new }
let(:survey) { user.surveys.create }
it "should define the association" do
expect(survey).to have(:no).errors_on(:user)
end
end
Upvotes: 1