2010-11-18 16 views
2

Ich versuche, die create Aktion meines Controllers zu testen. Ich verwende Devise für die Authentifizierung und habe die Methode before_filter verwendet, um den Zugriff auf die Aktion create für angemeldete Benutzer einzuschränken. Hier ist der relevante Teil meines Controllers.Testen von Controllern in Rails 3 mit Devise und RSpec

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 

In meinem Testfall möchte ich sicherstellen, dass ein angemeldeter Benutzer eine RawDataSet erstellen können. Ich denke, dass ich einen authentifizierten Benutzer nach den Anweisungen auf this Blogpost verspottet habe.

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 => "[email protected]" } 
    #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 

diesem Testfall Laufen verursacht den folgenden Fehler:

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' 

ich durch diesen Fehler bin ratlos. Bei weiterer Überprüfung ist @raw_data_set keine Instanz der RawDataSet-Modellklasse, sondern ein Benutzer? Dies ist, wie es aussieht, wenn ich p @raw_data_set

#<User:0x807a06a4 @name="User_1002"> 

Was zum Teufel ist hier los? Was mache ich falsch? Wie kann ich die Erstellungsaktion auf meinem Controller mit einem authentifizierten Benutzer testen?

Antwort

1

EDIT(total falsch erster Versuch entfernt)

Aufruf as_null_object im Wesentlichen die Mock sagt alle Nachrichten zu akzeptieren, die nicht gerodet werden und nur selbst zurück. Also, wenn Sie anrufen

current_user.raw_data_sets.build(params[:raw_data_set])

, die normalerweise einen neuen RawDataSet-current_user zugeordnet zurückkehren würde, anstatt Sie current_user wieder zu bekommen.

Also, wenn Sie versuchen, umleiten, übergibt @raw_data_set, übergeben Sie es die Mock anstelle einer RawDataSet Instanz, also der fehlerhaften Aufruf an user_url.

Ich denke, der Weg, damit umzugehen, ist nur einen echten Benutzer (oder eine Fabrik) zu verwenden und die Devise-Methoden darauf auszugeben. Also Ihre mock_users wird (zum Beispiel):

def mock_users(stubs={}) 
    @user = User.create(stubs) 
    end 

Jetzt current_user tatsächlich die Build tun und durch den Verein retten.

Puristen werden Ihnen sagen, dass Sie alles verhöhnen und ausstempeln sollen, bis Sie blau im Gesicht sind. Schrauben Sie das - Sie haben bessere Dinge zu tun. :)

Die andere Möglichkeit, dies zu erreichen, ist zu testen, dass die Build-Nachricht empfangen wird, ohne zu überprüfen, ob die Speicherung erfolgreich war. Vermutlich werden Ihre Modelltests bestätigen, dass das Speichern durch die Assoziation funktioniert - warum erneut im Controller testen?

+0

Das Problem ist, dass diese Zeile vom Controller: @raw_data_set = current_user.raw_data_sets.build (params [: raw_data_set]) gibt eine Instanz der User-Klasse in meinem Test zurück, was nicht das ist, was ich tun soll. Es sollte eine Instanz der RawDataSet-Klasse sein und zu RawDataSets # show umleiten. – jergason

+0

Danke für die Hilfe. Ich bekomme immer noch den Dreh von RSpec, also war das sehr hilfreich. – jergason

0

Wenn Sie beispielsweise das Verhalten des Anmeldevorgangs ändern müssen, können Sie Controller erben und sie überschreiben. können Sie die Anweisungen von hier https://github.com/plataformatec/devise die konfigurierenden Controller folgen.

Verwandte Themen