Domanda

Sto retroattivamente a scrivere alcuni test, utilizzando RSpec, per un progetto Rails.

Sto usando la gemma CanCan per fornire l'autorizzazione. Ho deciso di scrivere una specifica che metterà alla prova il modello ability.rb. Allora sono andato a testare i miei modelli rimanenti.

Ho passato verso i controllori, e ho incontrato un enorme intoppo: sto testando le mie capacità di nuovo

In sostanza, devo spegnere una serie di modelli, e spegnere le loro associazioni; altrimenti la risposta restituisce solo 403 Forbidden.
La ragione di questo, è che il controller è fondamentalmente il compito di preoccuparsi di autorizzazione.

Non sono del tutto sicuro dove andare da qui. Sto spegnendo fino a 6 modelli, solo per scrivere un singolo test. I so il lavoro capacità, questo è quello che è per ability_spec.rb.

Quindi questa domanda è in realtà 2 volte:

  1. dovrei testare il modello di capacità separatamente?
  2. Qualora il test del controller riguarderanno permessi appropriati?

Modifica     require 'spec_helper'     includere Devise :: TestHelpers # per dare l'accesso a specifiche aiutanti

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

Grazie,
Robbie

È stato utile?

Soluzione

Lo faccio testare il modello Cancan separatamente, ma testare ciò che permetterà in quali condizioni.

Credo che se si sta facendo le cose come

authorize! :take_over, @the_world

Poi io che si dovrebbe essere in prova che nel controller. Non sono sicuro che è necessario testare tutti i 6 versioni dei modelli però.

È possibile spegnere l'Ability.can? di classe e lo hanno rispondere vero / falso, e la prova di come le vostre maniglie del controller quando può (e più importante) quando non può continuare.

Altri suggerimenti

Non sono sicuro se questo è troppo tardi per voi, ma ho appena incontrato lo stesso problema, e risolto utilizzando il seguente codice di esempio -

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

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

Ho spense Abilità # nuovo, dandomi un riferimento all'istanza di abilità che controlli l'utente corrente. Poi, posso spegnere determinate abilità, come questo:

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

o dare privilegi di amministratore:

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

Simile alla risposta di Sam, ma dalla pagina wiki CanCan sul test:

Regolatore test

Se si desidera la funzionalità di autorizzazione di prova a livello di controller una possibilità è quella di log-in l'utente che dispone delle autorizzazioni appropriate.

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

In alternativa, se si desidera verificare il comportamento del controller in modo indipendente da ciò che è all'interno della classe Ability, è facile spegnere la capacità con qualsiasi comportamento che si desidera.

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

Se si dispone delle autorizzazioni molto complessi può portare a molte possibilità di diramazione. Se questi sono tutti testati nello strato controllore quindi può portare a test lenti e gonfio. Invece Mi consiglia di mantenere autorizzazione controllore test luce e verificare la funzionalità autorizzazione più approfondito nel modello di capacità attraverso test unitari come mostrato nella parte superiore.

Credo che le esigenze di autorizzazione da fare soprattutto per controller per assicurarsi che la vostra autorizzazione sta funzionando correttamente con il controller. Quindi, per rendere più DRY è possibile implementare il proprio matcher per essere utilizzato in questo modo

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

e quindi implementare queste matchers con il proprio modo di prova come sarà autorizzato una richiesta o non

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

Perché non includere un

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

nella vostra capacità e poi hanno un param is_ultrasuper in uno dei tuoi utenti di fissaggio:

one: 
  id: 1 
  username: my_username 
  is_ultrasuper: 1

quindi accedere a tale utente nella configurazione di test. Questo nei test si dovrebbe essere in grado di fare nulla.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top