Reputation: 294
I'm making my first steps with rails and am reading M.Hartl's tutorial. I'm trying to write some simple test to check that following relationship is deleted when we delete user
describe "deleting user should delete relationship" do
before do
other_user.destroy
end
expect(@user.name).to eq("Tom") # undefined method name
expect(@user.followers).to include(other_user) # undefined method followers
its(:followers) { should_not include(other_user) } # this works
end
why @user.name
and @user.followers
are not defined? how can I access it? I'd expect at least name to be there as it's property of user model... is it somehow private and I need to write accessor to access it? Same for followers.. do I have to write separate method to return user's followers?
User model looks like this:
class User < ActiveRecord::Base
has_many :microposts, dependent: :destroy
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_users, through: :relationships, source: :followed
has_many :reverse_relationships, foreign_key: "followed_id", class_name: "Relationship", dependent: :destroy
has_many :followers, through: :reverse_relationships, source: :follower # we could omit source in this case since, in the case of a :followers attribute, Rails will singularize “followers” and automatically look for the foreign key follower_id in this case.
...
Upvotes: 0
Views: 161
Reputation: 96
You have to mock your object @user. The easy way is
let(@user){ User.new(name: "Foo") }
This instanciate a new User to @user. I prefer to use FactoryGirl for do that. But User.new will solve your problem
Upvotes: 0
Reputation: 44675
You can't use expectation outside of tests - you need to wrap them in:
it 'name is Tom' do
expect(@user.name).to eq 'Tom'
end
it 'is followed by deleted user' do
expect(@user.followers).to include(other_user)
end
its
method is a handy shortcut:
its(:attribute) { should be_present } # test name: Its attribute should be present
is the same as (except for the better test name):
it 'has present attribute' do # test name: It has present attribute
subject.attribute.should be_present
end
Note that you need to have subject
defined in your test suite to use the second form. If you have subject defined, you should use it instead of instance variables (so you can easily change the subject without altering all your tests). So your tests should rather look like this:
its(:name) { should eq 'Tom' }
its(:followers) { should_not include(other_user) }
The reason why it is not working the way you wrote it is that @user
is an instance variable, which you are trying to execute in the context of class. This naturally returns 'nil', since the class did not define such variable.
Upvotes: 3