2010-06-11 2 views
5

У меня возникли проблемы с пониманием, почему я не могу заглушить этот метод контроллера :load_user, так как все мои тесты терпят неудачу, если я изменяю фактическую реализацию :load_user, чтобы не возвращать и экземпляр @user.Stubbing a before_filter с RSpec

Может ли кто-нибудь понять, почему мой заглушка (controller.stub!(:load_user).and_return(@user)), похоже, не вызван, когда RSpec делает запрос к контроллеру?

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 

Может ли кто-нибудь понять, почему мой заглушка не работает? Как я уже сказал, мои тесты проходят только в том случае, если я уверен, что load_user работает, если нет, все мои тесты терпят неудачу, из-за чего я думаю, что RSpec не использует созданный мною заглушку.

+0

Извините, у меня нет реального ответа, но убедитесь, что контроллер, который вы выполняете в ваших тестах, и контроллер, выполняющий код, являются одним и тем же экземпляром. Вы можете проверить их 'object_id', чтобы убедиться. – x1a4

ответ

8

гася load_user перерывы тесты, потому что гася на метод кастраты его. Когда контроллер вызывает load_user, он больше не запускает ваш исходный код. Теперь он возвращает только то, что вы указываете в and_return(...) (который возвращается в стек обратного вызова ActionController, который игнорирует что-либо, кроме false).

Ваш код контроллера не использует возвращаемое значение этого метода; он использует переменную, созданную в пределах. Поскольку исходный код для метода load_user не выполняется, переменная экземпляра @user никогда не создается. (Переменная @user в ваших тестах видна только вашим тестам.)

Но со всеми другими заглушками у вас нет, я не вижу причин, по которым вам нужно будет отключить load_user. До тех пор, пока вы завершите current_user, чтобы вернуть @user (который, как я полагаю, выполняется в методе sign_in), тогда не должно быть необходимости.

+0

Это отличное объяснение, если бы я мог проголосовать за него больше. Большое вам спасибо, объяснение о возврате @user против экземпляра @user действительно помогло ему нажать на меня. – TheDelChop

2

вы также можете попробовать, чтобы убедиться, что заглушки работ делает утверждение, как

controller.current_user.should == @user 
Смежные вопросы