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?

È stato utile?

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.

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