Reputation: 149
When I run the following command rspec spec/models/vote_spec.rb
, I get the following error:
Failures:
1) Vote validations value validation only allows -1 or 1 as values
Failure/Error: expect ( @post.votes ).to eq(-1)
NoMethodError:
undefined method `votes' for nil:NilClass
# ./spec/models/vote_spec.rb:7:in `block (4 levels) in <top (required)>'
Finished in 0.00255 seconds (files took 2.37 seconds to load)
1 example, 1 failure
Here's my code for vote_spec.rb
require 'rails_helper'
describe Vote do
describe "validations" do
describe "value validation" do
it "only allows -1 or 1 as values" do
expect ( @post.votes ).to eq(-1)
expect ( @post.votes ).to eq(1)
end
end
end
end
Sorry I am new to this, I guess my @post variable is not being set. Where should I look for this?
Upvotes: 1
Views: 284
Reputation: 6466
Correct. You're running into this error because your @post
variable is nil. What do you mean by "where should I look for this?"
In order to fix this error, you need to define @post
somehow in your spec, above the two "examples" in your it
block. (This could go in the it
block, or in a describe
or let
block above the it
). Two options. Create the object long-form:
@post = Post.create(attribute_hash_here)
or use a factory of some sort (example below uses FactoryGirl):
@post = create(:post)
As it stands, however, were you to do that, your spec would still fail, because it has contrasting expectations:
expect ( @post.votes ).to eq(-1)
expect ( @post.votes ).to eq(1)
Unless the votes
method on Post
both returns a value AND alters that value, @post.votes
will equal EITHER -1
or 1
. So if it passes the first expectation, it will fail the second, and if it passes the second, it will fail the first.
** EDIT ** -- As ChrisBarthol pointed out, it's not clear why you need @post
to exist at all. If you're just testing a vote
's attribute validations, why not just test that object on its own?
Upvotes: 3
Reputation: 4959
First off these are model validations, and you are validating the vote model not the post model, so you should be setting @vote, and not @post. Secondly your test says you expect the value to equal -1 and then 1. How could it be both at the same time? Where are you setting the value such that you expect it? You have to restructure you tests so you are only testing one item at a time.
require 'rails_helper'
describe Vote do
let(:post) { Post.new(whatever post params) }
before { @vote=post.votes.build(whatever vote parameters you have) }
subject { @vote }
describe "validations" do
describe "+1 value valdiation" do
before { @vote.value = 1 }
it { should be_valid }
end
describe "-1 value valdiation" do
before { @vote.value = -1 }
it { should be_valid }
end
describe "other value valdiation" do
before { @vote.value = 0 }
it { should_not be_valid }
end
end
end
I'm guessing at your relationships. There are also better ways to write these tests but that should lead you down the right road.
Upvotes: 2