2010-06-11 18 views
5

Ich habe Probleme zu verstehen, warum ich nicht scheinen kann, diese Controller-Methode :load_user stub, da alle meine Tests fehlschlagen, wenn ich die tatsächliche Implementierung von :load_user nicht zurück und Instanz von @user.Stubbing ein Before_filter mit RSpec

Kann jemand sehen, warum mein Stub (controller.stub!(:load_user).and_return(@user)) scheinbar nicht aufgerufen wird, wenn RSpec eine Anfrage an den Controller stellt?

require 'spec_helper' 

describe TasksController do 

    before(:each) do 
    @user = Factory(:user) 
    sign_in @user 
    @task = Factory(:task) 
    User.stub_chain(:where, :first).and_return(@user) 
    controller.stub!(:load_user).and_return(@user) 
    end 

    #GET Index 
    describe "GET Index" do 

    before(:each) do 
     @tasks = 7.times{Factory(:task, :user => @user)} 
     @user.stub!(:tasks).and_return(@tasks) 
    end 

    it "should should find all of the tasks owned by a user" do 
     @user.should_receive(:tasks).and_return(@tasks) 
     get :index, :user_id => @user.id 
    end 

    it "should assign all of the user's tasks to the view" do 
     get :index, :user_id => @user.id 
     assigns[:tasks].should be(@tasks)  
    end 
    end 

    #GET New 
    describe "GET New" do 

    before(:each) do 
     @user.stub_chain(:tasks, :new).and_return(@task) 
    end 

    it "should return a new Task" do 
     @user.tasks.should_receive(:new).and_return(@task) 
     get :new, :user_id => @user.id 
    end 
    end 

    #POST Create 
    describe "POST Create" do 

    before(:each) do 
     @user.stub_chain(:tasks, :new).and_return(@task) 
    end 

    it "should create a new task" do 
    @user.tasks.should_receive(:new).and_return(@task) 
     post :create, :user_id => @user.id, :task => @task.to_s 
    end 

    it "saves the task" do 
     @task.should_receive(:save) 
     post :create, :user_id => @user.id, :task => @task 
    end 

    context "when the task is saved successfully" do 

     before(:each) do 
     @task.stub!(:save).and_return(true) 
     end 

     it "should set the flash[:notice] message to 'Task Added Successfully'"do 
     post :create, :user_id => @user.id, :task => @task 
     flash[:notice].should == "Task Added Successfully!" 
     end 

     it "should redirect to the user's task page" do 
     post :create, :user_id => @user.id, :task => @task 
     response.should redirect_to(user_tasks_path(@user.id)) 
     end 
    end 

    context "when the task isn't saved successfully" do 

     before(:each) do 
     @task.stub(:save).and_return(false) 
     end 

     it "should return to the 'Create New Task' page do" do 
     post :create, :user_id => @user.id, :task => @task 
     response.should render_template('new') 
     end 
    end 
    end 

    it "should attempt to authenticate and load the user who owns the tasks" do 

    context "when the tasks belong to the currently logged in user" do 

     it "should set the user instance variable to the currently logged in user" do 
     pending 
     end 

    end 

    context "when the tasks belong to another user" do 

     it "should set the flash[:notice] to 'Sorry but you can't view other people's tasks.'" do 
     pending 
     end 

     it "should redirect to the home page" do 
     pending 
     end 
    end 
    end 
end 

class TasksController < ApplicationController 
    before_filter :load_user 

    def index 
    @tasks = @user.tasks 
    end 

    def new 
    @task = @user.tasks.new 
    end 

    def create 
    @task = @user.tasks.new 
    if @task.save 
     flash[:notice] = "Task Added Successfully!" 
     redirect_to user_tasks_path(@user.id) 
    else 
     render :action => 'new' 
    end 
    end 

    private 

    def load_user 
    if current_user.id == params[:user_id].to_i 
     @user = User.where(:id => params[:user_id]).first 
    else 
     flash[:notice] = "Sorry but you can't view other people's tasks." 
     redirect_to root_path 
    end 
    end 
end 

Kann jemand sehen, warum mein Stub nicht funktioniert? Wie ich schon sagte, meine Tests bestehen nur, wenn ich sicher bin, dass load_user funktioniert, wenn nicht, scheitern alle meine Tests, was meinen, dass RSpec nicht den von mir erstellten Stub verwendet.

+0

Entschuldigung, ich habe keine echte Antwort, aber stellen Sie sicher, dass der Controller, den Sie in Ihren Tests stubbing und der Controller, der tatsächlich Code ausführt, dieselbe Instanz ist. Sie können ihre 'object_id' überprüfen, um sicherzustellen. – x1a4

Antwort

8

load_user bricht Ihre Tests Stubbing, weil die Methode Neutra stubbing es. Wenn der Controller load_user aufruft, wird der ursprüngliche Code nicht mehr ausgeführt. Es gibt jetzt nur das zurück, was Sie in and_return(...) angeben (das wird an den Callback-Stack ActionController zurückgegeben, der alles andere als false ignoriert).

Ihr Controller-Code verwendet nicht den Rückgabewert dieser Methode. Es verwendet die Variable instanziiert innerhalb es. Da der ursprüngliche Code für die load_user-Methode nicht ausgeführt wird, wird die Instanzvariable @user niemals instanziiert. (Die @user Variable in Ihren Tests ist nur für Ihre Tests sichtbar.)

Aber mit all den anderen Stubs, die Sie haben, sehe ich keinen Grund, warum Sie load_user überhaupt ausstoßen sollten. Solange Sie current_user stubbing @user zurückgeben (was ich davon ausgehe, wird in der sign_in Methode gemacht), dann sollte es keine Notwendigkeit geben.

+0

Das ist eine großartige Erklärung, wenn ich mehr abstimmen könnte. Vielen Dank, die Erklärung über die Rückgabe von @user vs instantiating @user hat mir wirklich geholfen, für mich zu klicken. – TheDelChop

2

können Sie auch zu überprüfen versuchen, dass die Stub-Werke eine Behauptung zu tun wie

controller.current_user.should == @user