1

User私は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

これはうまく機能し、誰かが管理者ユーザーを誤って削除した場合、データベースのロールバックが発生します。

問題は、管理者以外のユーザー (Factory Girl によって生成された) でテストした場合でも、ユーザーの削除アクションが壊れているように見えることです。これは私の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

このテストを実行するたびに、次のエラーが発生します。

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

@userただし、の admin 属性はデフォルトで false に設定されているため、エラーは発生しません。

誰か助けてくれませんか?

ありがとう...

4

4 に答える 4

1

次の変更を行います。

before_destroy :ensure_an_admin_remains

def ensure_an_admin_remains
  if self.admin == true and User.where( :admin => true ).count.zero?
    raise "Can't delete Admin."
  end
end
于 2013-03-03T17:02:38.123 に答える
1

私は間違っているかもしれませんが、仕様は空のデータベースで始まりますよね? したがって、データベースに管理者ユーザーは存在しません。したがって、delete を呼び出すと、常に User.where("admin = ?", true).count がゼロになります。

テストの前にユーザー管理者を作成してみてください

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
于 2013-03-03T16:08:27.537 に答える
1

別の方法として、呼び出された関数ensure_an_admin_remainsを などのパブリック関数にすることもできcheck_admin_remainsます。

check_admin_remainsその後、あたかも他の関数であるかのように、のロジックをテストできます。

次に、別のテストで、次のように、データベースとの対話なしで破棄時に関数が呼び出されることを確認できます。

let(:user) { build_stubbed(:user) }

it 'is called on destroy' do
  expect(user).to receive(:check_admin_remains)

  user.run_callbacks(:destroy)
end
于 2016-11-17T14:58:54.693 に答える