Testen Controller in Rails 3 mit Devise und RSpec
-
26-09-2019 - |
Frage
Ich versuche, meine Controller create
Aktion zu testen. Ich verwende Devise für die Authentifizierung und haben die before_filter Methode den Zugriff auf die create
Aktion eingeloggten verwendet Benutzer. Hier ist der relevante Teil meiner 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
In meinem Testfall möchte ich sicherstellen, dass ein angemeldeter Benutzer eine RawDataSet erstellen können. Ich denke, dass ich einen authentifizierten Benutzer gemäß den Anweisungen auf dieser Blogeintrag verspottet .
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
Mit diesem Testfall Laufen verursacht die 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 bin von diesem Fehler verwirrt. Bei mehr Kontrolle ist @raw_data_set nicht eine 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 teste die Wirkung auf meinem Controller mit einem authentifizierten Benutzer erstellen?
Lösung
Bearbeiten (total falsch erster Versuch entfernt)
Beim as_null_object
sagt im Wesentlichen der mock alle Nachrichten zu akzeptieren, die nicht gerodet werden und zurück selbst gerade. Also, wenn Sie anrufen
current_user.raw_data_sets.build(params[:raw_data_set])
, die normalerweise einen neuen RawDataSet
zu current_user
zugeordnet zurückkehren würde, Sie current_user
wieder stattdessen bekommen.
Also, wenn Sie, um die Anrufweiterleitung versuchen, in @raw_data_set
vorbei, ich ist es, die Mock statt einer RawDataSet
Instanz zu übergeben, so dass der verirrten Aufruf user_url
.
Ich denke, die Art und Weise, dies zu umgehen ist nur einen echten Benutzer (oder eine Factory) und Stummel aus der Devise Methoden darauf. Also Ihre mock_users
wird (zum Beispiel):
def mock_users(stubs={})
@user = User.create(stubs)
end
Jetzt current_user
wird die Build tatsächlich tun und durch die Assoziation speichern.
Puristen werden Ihnen sagen, zu verspotten und Stub alles, bis Sie blau im Gesicht. Schraube, dass - Sie haben bessere Dinge zu tun. :)
Der andere Weg, um diesen Ansatz zu testen, ob die Build-Nachricht ohne Überprüfung empfangen wird, ob das gelungen retten. Vermutlich Ihre Modelltests überprüfen, ob durch den Verein Speicher funktioniert - warum Test erneut im Controller
Andere Tipps
Wenn Sie das Verhalten von Sign-in etwas Bestimmtes zum Beispiel ändern tun, können Sie von devise Controller erben und sie überschreiben. Sie können die Anweisung von hier folgen https://github.com/plataformatec/devise die Konfiguration von Controllern.