Rimanendo DRY durante la prova di un controllore, autorizzata mediante CanCan
-
27-09-2019 - |
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:
- dovrei testare il modello di capacità separatamente?
- 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
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.