rspec controller testing, Expected response to be a <redirect>, but was <200>

factory-bot, rspec, ruby-on-rails

Solution

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.

Problem

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?

Original source