Search code examples
ruby-on-railsruby-on-rails-3rspecrspec2rspec-rails

How to test after_destroy callback in Rails and RSpec?


I have this User class in Ruby on Rails:

class User < ActiveRecord::Base

  after_destroy :ensure_an_admin_remains

  private

  def ensure_an_admin_remains
    if User.where("admin = ?", true).count.zero?
      raise "Can't delete Admin."
    end
  end

end

This works great and causes a database rollback if someone accidentally deletes an admin user.

The problem is that it seems to break the user delete action, even when testing with a non-admin user (generated by Factory Girl). This is my user_controller_spec.rb:

describe 'DELETE #destroy' do

  before :each do
    @user = create(:non_admin_user)
    sign_in(@user)
  end

  it "deletes the user" do
    expect{ 
      delete :destroy, id: @user
    }.to change(User, :count).by(-1)
  end

end

Whenever I run this test, I get this error:

Failure/Error: expect{
count should have been changed by -1, but was changed by 0

There shouldn't be any error, though, because @user's admin attribute is set to false by default.

Can anybody help me out here?

Thanks...


Solution

  • I may be wrong but, Your spec start with empty database right? So there is no admin user present in your db. So when you call delete, you'll always have User.where("admin = ?", true).count equal to zero

    Try creating an user admin before your test

    describe 'DELETE #destroy' do
    
      before :each do
        create(:admin_user)
        @user = create(:non_admin_user)
        sign_in(@user)
      end
    
      it "deletes the user" do
        expect{ 
          delete :destroy, id: @user
        }.to change(User, :count).by(-1)
      end
    
    end