1

Railsプロジェクト用に、RSpecを使用していくつかのテストをさかのぼって作成しています。

CanCangemを使用して認証を提供しています。ability.rbモデルをテストするスペックを書くことにしました。その後、残りのモデルをテストしました。

私はコントローラーに移りました、そして私は巨大な障害に遭遇しました:私は自分の能力をもう一度テストしています!

基本的に、私は一連のモデルをスタブ化し、それらの関連付けをスタブ化する必要があります。それ以外の場合、応答は単にを返します403 Forbidden
その理由は、基本的にはコントローラーが認証の心配をしているからです。

ここからどこへ行けばいいのかよくわかりません。1つのテストを作成するために、最大6つのモデルをスタブします。私は能力が機能することを知っています、それability_spec.rb目的です。

したがって、この質問は実際には2つあります。

  1. 能力モデルを個別にテストする必要がありますか?
  2. コントローラのテストは適切な権限に関係する必要がありますか?

Edit require'spec_helper' include Devise :: TestHelpers#スペックにヘルパーへのアクセスを許可する

describe TokensController do
  before(:each) do
    @mock_user = User.new(:username => "bob", :email => "user@user.com", :password => "longpassword")
    @mock_user.role = "admin"
    sign_in @mock_user
    #Ability.stub!('can').and_return(true)
  end
  it "should let me see grids/:g_id/tokens index" do
    test_grid = mock_model(Grid)
    test_token = mock_model(Token)
    Grid.stub!(:find).and_return(test_grid)
    Token.stub!(:find).and_return(test_token)
    get 'index'

    a1 = Ability.new(@mock_user)
    a1.can?(:index, Token).should be_true # This line works fine; as it should
    puts response.status #This returns 403, which means CanCan::AccessDenied was raised
  end
end

ありがとう、
ロビー

4

5 に答える 5

4

これが手遅れかどうかはわかりませんが、同じ問題が発生し、次のコードサンプルを使用して解決しました-

before do
  @user = Factory.create(:user)
    sign_in @user

    @abilities = Ability.new(@user)
    Ability.stub(:new).and_return(@abilities)
  end
end

現在のユーザーを制御するAbilityのインスタンスへの参照を提供して、Ability#newをスタブアウトしました。次に、次のような特定の能力をスタブアウトできます。

@abilities.stub!(:can?).with(:destroy, regatta).and_return(true)

または管理者権限を付与します。

@abilities.stub!(:can?).and_return(false)

于 2010-11-10T19:40:45.327 に答える
2

私はカンカンモデルを個別にテストしますが、どのような条件で何ができるかをテストします。

私はあなたが次のようなことをしているなら

authorize! :take_over, @the_world

次に、コントローラーでそれをテストする必要があると思います。ただし、モデルの6つのバージョンすべてをテストする必要があるかどうかはわかりません。

あなたはAbility.canをスタブアウトすることができますか?クラスを作成し、true / falseで応答させ、コントローラーが続行できない場合(さらに重要な場合)にコントローラーがどのように処理するかをテストします。

于 2010-10-28T21:09:11.693 に答える
1

サムの答えに似ていますが、テストに関するCanCanwikiページから:

コントローラーのテスト

コントローラレベルで認証機能をテストする場合、1つのオプションは、適切な権限を持つユーザーにログインすることです。

user = User.create!(:admin => true) # I recommend a factory for this
# log in user however you like, alternatively stub `current_user` method
session[:user_id] = user.id 
get :index
assert_template :index # render the template since he should have access

または、Abilityクラス内にあるものとは別にコントローラーの動作をテストする場合は、任意の動作で能力を簡単にスタブ化できます。

def setup
  @ability = Object.new
  @ability.extend(CanCan::Ability)
  @controller.stubs(:current_ability).returns(@ability)
end

test "render index if have read ability on project" do
  @ability.can :read, Project
  get :index
  assert_template :index
end

非常に複雑な権限がある場合、多くの分岐の可能性につながる可能性があります。これらがすべてコントローラーレイヤーでテストされると、テストが遅くなり、肥大化する可能性があります。代わりに、コントローラーの承認テストを軽量に保ち、上部に示すように、単体テストを通じてアビリティモデルで承認機能をより徹底的にテストすることをお勧めします。

于 2013-01-28T13:27:22.263 に答える
1

承認がコントローラーで正しく機能していることを確認するには、主にコントローラーに対して承認を行う必要があると思います。だからそれを乾かすmatcherためにあなたはこのように使われるあなた自身を実装することができます

let!(:user) {create :user}
before { login_user_request user}

it "grants admin access to show action" do
  expect{ get :show, {id: user.id} }.to be_authorized
end
it "denies user access to edit action" do
  expect{ get :edit, {id: user.id} }.to be_un_authorized
end

次に、リクエストがどのように承認されるかをテストする独自の方法でこれらのマッチャーを実装します

RSpec::Matchers.define :be_authorized do
  match do |block|
    block.call
    expect(response).to be_success
  end

  def supports_block_expectations?
    true
  end
end

RSpec::Matchers.define :be_un_authorized do
  match do |block|
    expect{
      block.call
    }.to raise_error(Pundit::NotAuthorizedError)
  end

  def supports_block_expectations?
    true
  end
end
于 2016-02-14T08:48:02.800 に答える
0

含めてみませんか

can :manage, :all do
  user.is_ultrasuper == 1
end

アビリティで、フィクスチャユーザーの1人にis_ultrasuperパラメータを設定します。

one: 
  id: 1 
  username: my_username 
  is_ultrasuper: 1

次に、テストのセットアップ時にこのユーザーをログインします。これはテストでは何でもできるはずです。

于 2011-10-16T03:50:54.187 に答える