controllori test in Rails 3 con Devise e RSpec
-
26-09-2019 - |
Domanda
Sto cercando di testare l'azione create
del mio controller. Sto usando Devise per l'autenticazione, e hanno usato il metodo before_filter per limitare l'accesso all'azione create
a logged- gli utenti. Qui è la parte rilevante del mio controller.
class RawDataSetsController < ApplicationController
before_filter :authenticate_user!, :except => [:show, :index, :download]
def create
@raw_data_set = current_user.raw_data_sets.build(params[:raw_data_set])
if @raw_data_set.save
redirect_to @raw_data_set
else
render "new"
end
end
end
Nel mio caso di test voglio fare in modo che un utente connesso può creare un RawDataSet. Penso che ho preso in giro fino a un utente autenticato secondo le istruzioni su questo post del blog .
require 'spec_helper'
describe RawDataSetsController do
include Devise::TestHelpers
def mock_users(stubs={})
@user ||= mock_model(User, stubs).as_null_object
end
def log_in_test_user
attr = { :username => "Foobar", :email => "doineedit@foobar.com" }
#mock up an authentication in warden as per http://www.michaelharrison.ws/weblog/?p=349
request.env['warden'] = mock(Warden, :authenticate => mock_users(attr),
:authenticate! => mock_users(attr),
:authenticate? => mock_users(attr))
end
before do
@rds = Factory(:raw_data_set)
end
describe "POST 'create'" do
before do
@attr = {
:organism_name => "Beef Jerky",
:mass_spec_type => "My Stomach",
}
end
describe "logged in user" do
it "should create a raw_data_set when the user is logged in" do
log_in_test_user
lambda do
post :create, :raw_data_set => @attr
end.should change(RawDataSet, :count).by(1)
end
end
end
end
L'esecuzione di questo test case causa l'errore seguente:
1) RawDataSetsController POST 'create' logged in user should create a raw_data_set when the user is logged in
Failure/Error: post :create, :raw_data_set => @attr
undefined method `user_url' for #<RawDataSetsController:0x0000010175af88>
# ./app/controllers/raw_data_sets_controller.rb:7:in `create'
Sono sconcertato da questo errore. Su più di ispezione, @raw_data_set non è un'istanza della classe del modello RawDataSet, ma un utente? Questo è quello che sembra quando ho p @raw_data_set
#<User:0x807a06a4 @name="User_1002">
Che diavolo sta succedendo? Che cosa sto facendo di sbagliato? Come faccio a testare il Crea azione sul mio controller con un utente autenticato?
Soluzione
Modifica (totalmente sbagliato primo tentativo rimosso)
Calling as_null_object
racconta essenzialmente la finta di accettare tutti i messaggi che non sono hanno spento e solo auto di ritorno. Così, quando si chiama
current_user.raw_data_sets.build(params[:raw_data_set])
che normalmente restituire una nuova RawDataSet
associato a current_user
, invece si ottiene di nuovo current_user
.
Quindi, quando si tenta di chiamare reindirizzamento, passando @raw_data_set
, si sta passando il mock invece di un'istanza RawDataSet
, quindi la chiamata erranti per user_url
.
Penso che il modo per gestire questa situazione è sufficiente utilizzare un vero e proprio utente (o una fabbrica) e spegnere i metodi Devise su di esso. Così il vostro mock_users
diventa (per esempio):
def mock_users(stubs={})
@user = User.create(stubs)
end
Ora current_user
effettivamente fare la costruzione e salvare attraverso l'associazione.
I puristi vi dirà di deridere e spegnere tutto finché non si è blu in faccia. Vite che - hai avuto di meglio da fare. :)
L'altro modo per avvicinarsi a questo è quello di testare che il messaggio build è ricevuto senza verificare se il salvataggio è riuscito. Presumibilmente i test modello verificheranno che il risparmio energetico attraverso l'associazione funziona - perché ancora una volta prova del controller
Altri suggerimenti
Se avete bisogno di fare qualcosa di specifico, ad esempio il cambiamento del comportamento di accesso, è possibile ereditare da controllori concepire e li sovrascrive. è possibile seguire le istruzioni da qui https://github.com/plataformatec/devise i controllori configurazione.