I'm using rspec and Factory Girl for testing. When testing the POST #create section of my posts_controller I'm getting the error in the title.
Failures:
1) PostsController POST #create with valid attributes redirects to the post
Failure/Error: response.should redirect_to Post.last
Expected response to be a <redirect>, but was <200>
# ./spec/controllers/posts_controller_spec.rb:59:in `block (4 levels) in <top (required)>'
This is the code from the spec being tested. I'm sure it's not the most efficient way of doing this, but it does work.
def create
@post = Post.new(
:text => post_params[:text],
:embed => post_params[:embed],
:user => current_user,
:title => post_params[:title],
:tag_list => post_params[:tag_list],
:cagegory_ids => post_params[:category_ids]
)
if @post.save
redirect_to @post
else
render 'new'
end
end
...
private
def post_params
params.require(:post).permit(:title, :text, :embed, :user_id, :tag_list,
:category_ids => [])
end
Here's the factory.
FactoryGirl.define do
factory :post do
title { Faker::Lorem.characters(char_count = 20) }
text { Faker::Lorem.characters(char_count = 150) }
user
categories {
Array(5..10).sample.times.map do
FactoryGirl.create(:category)
end
}
end
end
And the relevant part of the spec
describe "POST #create" do
context "with valid attributes" do
it "saves the new post" do
expect{
post :create, post: FactoryGirl.create(:post).attributes
}.to change(Post,:count).by(1)
end
it "redirects to the post" do
post :create, post: FactoryGirl.create(:post).attributes
response.should redirect_to Post.last
end
end
end
The other test, "saves the new post," works fine. I've tried other variations of the redirect_to line, such as "redirect_to(posts_path(assigns[:post])) and it throws the same error.
Any ideas?
OK, I fixed my problem. It isn't pretty but it works.
The issue is with Factory Girl and associations, and I'm definitely not the first to have that problem, but none of the other solutions worked.
I ended up adding this before :each at the top of the POST #create section...
describe "POST #create" do
before :each do
Post.destroy_all
@cat = FactoryGirl.create(:category)
@newpost = FactoryGirl.build(:post)
@post_params = {category_ids: [@cat.id]}.merge(@newpost.attributes)
end
...
...to put the post params into a new hash that I could call later on in the code like this...
it "saves the new post" do
expect{
post :create, post: @post_params
}.to change(Post,:count).by(1)
end
it "redirects to the post" do
post :create, post: @post_params
response.should redirect_to Post.last
end
So this is solved. It adds a bit of overhead to the test but it works. I won't mark this as THE solution for a couple of days in case someone else comes around with some better, simpler code. I definitely welcome any more ideas.
I assume the problem is in factory. Most likely post instance didn't pass validations and controller renders new
view, which is not redirect, but success 200. Add logger in the controller and take a look if record actually saves. You can also read through test log tail -f log/test.log
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With