Hedselu
Hedselu

Reputation: 95

Ruby on rails rspec destroy count fails

I've written some tests for simple application. I'm having problem with #destroy method in my authors_controller. As I've done this from some tutorials (many sources shows similar approach) I guess it should work, but such error occurs:

Failure/Error: expect { delete :destroy, id: author.id }.to change(Author, :count).by(-1) expected #count to have changed by -1, but was changed by 0

Here's my code:

author_controller_spec.rb

require 'rails_helper'                        

describe AuthorsController do                 
  let(:author) { FactoryGirl.create(:author) }

  describe 'DELETE #destroy' do                                                                            
    it 'deletes author' do                                                      
      expect { delete :destroy, id: author.id }.to change(Author, :count).by(-1)
    end                                                                         
  end                                                                           
end                                                                             

authors_controller.rb

class AuthorsController < ApplicationController
def show
@author = Author.find(params[:id])
end

def new
  @author = Author.new
end

def create
  @author = Author.new(author_params)
  if @author.save
    redirect_to @author
  else
    render 'new'
  end
end

def edit
  @author = Author.find(params[:id])
end

def update
  @author = Author.find(params[:id])

  if @author.update(author_params)
    redirect_to @author
  else
    render 'edit'
  end
end

def destroy
  @author = Author.find(params[:id])
  @author.books.each do |book|
  book.destroy if book.authors.count == 1
  end
  @author.destroy
  redirect_to authors_path
end

def index
  @author = Author.all
end

private

  def author_params
    params.require(:author).permit(:name, :surname, book_ids: [])
  end
end

Upvotes: 0

Views: 408

Answers (1)

Matt Gibson
Matt Gibson

Reputation: 14949

The let call is not made until the first time you mention the variable, as it's lazy evaluation. This means that within your expect block, you are both creating and destroying the record, leading to an overall change of 0.

Either create the author outside of the block:

describe AuthorsController do                 
  let(:author) { FactoryGirl.create(:author) }

  describe 'DELETE #destroy' do   
    author                                                                         
    it 'deletes author' do                                                      
      expect { delete :destroy, id: author.id }.to change(Author, :count).by(-1)
    end                                                                         
  end                                                                           
end 

Or, tell the let block not to evaluate lazily by using let!:

describe AuthorsController do                 
  let!(:author) { FactoryGirl.create(:author) }

  describe 'DELETE #destroy' do                                                                            
    it 'deletes author' do                                                      
      expect { delete :destroy, id: author.id }.to change(Author, :count).by(-1)
    end                                                                         
  end                                                                           
end 

Upvotes: 1

Related Questions